using System.Transactions;
using SIGCM2.Application.Abstractions;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.Audit;
using SIGCM2.Domain.Entities;
using SIGCM2.Domain.Exceptions;

namespace SIGCM2.Application.Secciones.Create;

public sealed class CreateSeccionCommandHandler : ICommandHandler<CreateSeccionCommand, SeccionCreatedDto>
{
    private readonly ISeccionRepository _repo;
    private readonly IMedioRepository _medioRepo;
    private readonly IAuditLogger _audit;

    public CreateSeccionCommandHandler(ISeccionRepository repo, IMedioRepository medioRepo, IAuditLogger audit)
    {
        _repo = repo;
        _medioRepo = medioRepo;
        _audit = audit;
    }

    public async Task<SeccionCreatedDto> Handle(CreateSeccionCommand command)
    {
        // Validate medio exists and is active (REQ-SEC-001)
        var medio = await _medioRepo.GetByIdAsync(command.MedioId);
        if (medio is null || !medio.Activo)
            throw new MedioNotFoundException(command.MedioId);

        var exists = await _repo.ExistsByCodigoInMedioAsync(command.MedioId, command.Codigo);
        if (exists)
            throw new SeccionCodigoDuplicadoEnMedioException(command.MedioId, command.Codigo);

        var seccion = Seccion.ForCreation(command.MedioId, command.Codigo, command.Nombre, command.Tipo);

        using var tx = new TransactionScope(
            TransactionScopeOption.Required,
            new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted },
            TransactionScopeAsyncFlowOption.Enabled);

        var newId = await _repo.AddAsync(seccion);

        await _audit.LogAsync(
            action: "seccion.create",
            targetType: "Seccion",
            targetId: newId.ToString(),
            metadata: new
            {
                after = new
                {
                    seccion.MedioId,
                    seccion.Codigo,
                    seccion.Nombre,
                    seccion.Tipo,
                },
            });

        tx.Complete();

        return new SeccionCreatedDto(
            Id: newId,
            MedioId: seccion.MedioId,
            Codigo: seccion.Codigo,
            Nombre: seccion.Nombre,
            Tipo: seccion.Tipo,
            Activo: seccion.Activo);
    }
}
