using System.Transactions;
using SIGCM2.Application.Abstractions;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.Audit;
using SIGCM2.Application.Common;

namespace SIGCM2.Application.Pricing.ChargeableChars.Delete;

/// <summary>
/// PRC-001 — Handler for DeleteChargeableCharConfigCommand.
/// Flow: load existing → open TX → DeleteAsync → audit → tx.Complete().
///
/// NOTE on SYSTEM_VERSIONING: SQL Server moves the deleted row to the _History table with
/// SysEndTime = deletion timestamp. This means:
///   - Current-state queries (no FOR SYSTEM_TIME) return nothing — effectively "deleted".
///   - Historical queries (FOR SYSTEM_TIME ALL / AS OF) still return the row — temporal audit intact.
/// This is intentional. A "physical delete" (bypass SYSTEM_VERSIONING) is not supported here.
///
/// Future FAC-001 will add a guard to block delete if the row was used in invoicing.
/// </summary>
public sealed class DeleteChargeableCharConfigCommandHandler
    : ICommandHandler<DeleteChargeableCharConfigCommand, DeleteChargeableCharConfigResponse>
{
    private readonly IChargeableCharConfigRepository _repo;
    private readonly IAuditLogger _audit;
    private readonly TimeProvider _timeProvider;

    public DeleteChargeableCharConfigCommandHandler(
        IChargeableCharConfigRepository repo,
        IAuditLogger audit,
        TimeProvider timeProvider)
    {
        _repo = repo;
        _audit = audit;
        _timeProvider = timeProvider;
    }

    public async Task<DeleteChargeableCharConfigResponse> Handle(
        DeleteChargeableCharConfigCommand command)
    {
        // 1. Load existing — ensures the row exists before opening TX.
        var existing = await _repo.GetByIdAsync(command.Id)
            ?? throw new KeyNotFoundException($"ChargeableCharConfig con Id={command.Id} no existe.");

        // 2. TX + delete + audit (fail-closed).
        using (var tx = new TransactionScope(
            TransactionScopeOption.Required,
            new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted },
            TransactionScopeAsyncFlowOption.Enabled))
        {
            await _repo.DeleteAsync(command.Id);

            await _audit.LogAsync(
                action: "tasacion.chargeable_char.delete",
                targetType: "ChargeableCharConfig",
                targetId: command.Id.ToString(),
                metadata: new
                {
                    before = new
                    {
                        id = existing.Id,
                        symbol = existing.Symbol,
                        productTypeId = existing.ProductTypeId,
                        isActive = existing.IsActive,
                        validFrom = existing.ValidFrom.ToString("yyyy-MM-dd"),
                    },
                    deletedOn = _timeProvider.GetArgentinaToday().ToString("yyyy-MM-dd"),
                });

            tx.Complete();
        }

        return new DeleteChargeableCharConfigResponse(Id: command.Id);
    }
}
