using Monitoring.Core.Domain.ServiceOrganizationManagement;

using Monitoring.Models;
using Monitoring.Repositories;
namespace Monitoring.Services.ServiceOrganization;

public class ServiceOrganizationService : IServiceOrganizationService
{
    private readonly IServiceOrganizationRepository _organizationRepository;
    private readonly AssetRepository _assetRepository;

    public ServiceOrganizationService(    
        IServiceOrganizationRepository organizationRepository,
        AssetRepository assetRepository)
    {
        _organizationRepository = organizationRepository;
        _assetRepository = assetRepository;
    }

    public async Task<List<ServiceOrganizationModel>> GetAllAsync()
    {
        var organizations = await _organizationRepository.GetAll();
        return organizations.Select(ServiceOrganizationModel.FromEntity).ToList();
    }
    
    public async Task<ServiceOrganizationModel?> GetByIdServiceOrganization(Guid id)
    {
        var organization = await _organizationRepository.GetById(id);
        return organization == null ? null : ServiceOrganizationModel.FromEntity(organization);
    }

    public async Task<Guid> CreateAsync(ServiceOrganizationModel createdOrganization)
    {
        // Use domain entity's factory method for proper encapsulation
        var name = ServiceOrganizationName.Create(createdOrganization.Name);
        var newOrganization = Core.Domain.ServiceOrganizationManagement.ServiceOrganization.Create(name);
        
        await _organizationRepository.Create(newOrganization);
        return newOrganization.Id.Value;
    }

    public async Task UpdateAsync(Guid id, ServiceOrganizationModel desiredOrganization)
    {
        var existingOrganization = await _organizationRepository.GetById(id);
        if (existingOrganization == null)
            throw new InvalidOperationException($"Организация с Id {id} не найдена");

        // Use domain value object for proper validation
        var name = ServiceOrganizationName.Create(desiredOrganization.Name);
        existingOrganization.Name = name;
        
        await _organizationRepository.Update(existingOrganization);
    }

    public async Task DeleteAsync(
        Guid id,
        CancellationToken cancellationToken)
    {
        var usedAssets = await _assetRepository.GetAssetsByServiceOrganizationIdAsync(id, cancellationToken);

        await _organizationRepository.Delete(id);
    }
}