using MediatR;
using IamService.Domain.AggregatesModel.OrganizationAggregate;
using IamService.Domain.Exceptions;

namespace IamService.API.Application.Commands.Organizations;

/// <summary>
/// EN: Handler for CreateOrganizationCommand.
/// VI: Handler cho CreateOrganizationCommand.
/// </summary>
public class CreateOrganizationCommandHandler : IRequestHandler<CreateOrganizationCommand, CreateOrganizationCommandResult>
{
    private readonly IOrganizationRepository _organizationRepository;
    private readonly ILogger<CreateOrganizationCommandHandler> _logger;

    public CreateOrganizationCommandHandler(
        IOrganizationRepository organizationRepository,
        ILogger<CreateOrganizationCommandHandler> logger)
    {
        _organizationRepository = organizationRepository;
        _logger = logger;
    }

    public async Task<CreateOrganizationCommandResult> Handle(
        CreateOrganizationCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Creating organization: {Name} with slug: {Slug}", request.Name, request.Slug);

        // EN: Check if slug is unique
        // VI: Kiểm tra slug có duy nhất không
        var isSlugUnique = await _organizationRepository.IsSlugUniqueAsync(request.Slug, cancellationToken: cancellationToken);
        if (!isSlugUnique)
        {
            _logger.LogWarning("Slug already exists: {Slug}", request.Slug);
            throw new DomainException($"Organization with slug '{request.Slug}' already exists.");
        }

        // EN: Validate parent organization if provided
        // VI: Kiểm tra tổ chức cha nếu được cung cấp
        if (request.ParentOrganizationId.HasValue)
        {
            var parent = await _organizationRepository.GetByIdAsync(
                request.ParentOrganizationId.Value,
                cancellationToken);

            if (parent == null)
            {
                throw new DomainException($"Parent organization with ID '{request.ParentOrganizationId}' not found.");
            }
        }

        // EN: Create new organization
        // VI: Tạo tổ chức mới
        var organization = Organization.Create(
            request.Name,
            request.Slug,
            request.Description,
            request.ParentOrganizationId);

        _organizationRepository.Add(organization);

        await _organizationRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation(
            "Organization {Name} created successfully with ID {Id}",
            organization.Name,
            organization.Id);

        return new CreateOrganizationCommandResult(
            organization.Id,
            organization.Name,
            organization.Slug,
            organization.Description,
            organization.ParentOrganizationId,
            organization.Status.Name,
            organization.CreatedAt);
    }
}
