namespace CashLineERP.Domain.Finance;

public sealed class PaymentSettlementBatchLine
{
    public long Id { get; private set; }
    public long PaymentSettlementBatchId { get; private set; }
    public string SourceDocumentType { get; private set; } = string.Empty;
    public long SourceDocumentId { get; private set; }
    public string SourceDocumentNumber { get; private set; } = string.Empty;
    public long? PartyId { get; private set; }
    public decimal InternalAmount { get; private set; }
    public decimal SettledAmount { get; private set; }
    public decimal FeeAmount { get; private set; }
    public decimal NetAmount { get; private set; }
    public string? ProviderReference { get; private set; }
    public string? Notes { get; private set; }
    public string SettlementStatusCode { get; private set; } = "MATCHED";

    public PaymentSettlementBatchLine(
        long paymentSettlementBatchId,
        string sourceDocumentType,
        long sourceDocumentId,
        string sourceDocumentNumber,
        long? partyId,
        decimal internalAmount,
        decimal settledAmount,
        decimal feeAmount,
        decimal netAmount,
        string? providerReference,
        string? notes,
        string settlementStatusCode)
    {
        if (sourceDocumentId <= 0)
        {
            throw new InvalidOperationException("Payment settlement line requires a valid source document.");
        }

        if (string.IsNullOrWhiteSpace(sourceDocumentType) || string.IsNullOrWhiteSpace(sourceDocumentNumber))
        {
            throw new InvalidOperationException("Payment settlement line source metadata is required.");
        }

        if (internalAmount <= 0m)
        {
            throw new InvalidOperationException("Payment settlement line internal amount must be greater than zero.");
        }

        if (settledAmount < 0m || feeAmount < 0m || netAmount < 0m)
        {
            throw new InvalidOperationException("Payment settlement line monetary amounts cannot be negative.");
        }

        PaymentSettlementBatchId = paymentSettlementBatchId;
        SourceDocumentType = sourceDocumentType.Trim().ToUpperInvariant();
        SourceDocumentId = sourceDocumentId;
        SourceDocumentNumber = sourceDocumentNumber.Trim().ToUpperInvariant();
        PartyId = partyId;
        InternalAmount = internalAmount;
        SettledAmount = settledAmount;
        FeeAmount = feeAmount;
        NetAmount = netAmount;
        ProviderReference = string.IsNullOrWhiteSpace(providerReference) ? null : providerReference.Trim();
        Notes = string.IsNullOrWhiteSpace(notes) ? null : notes.Trim();
        SettlementStatusCode = string.IsNullOrWhiteSpace(settlementStatusCode) ? "MATCHED" : settlementStatusCode.Trim().ToUpperInvariant();
    }

    private PaymentSettlementBatchLine()
    {
    }

    public void MarkException()
    {
        SettlementStatusCode = "EXCEPTION";
    }

    public void MarkResolved(string resolutionCode)
    {
        SettlementStatusCode = string.IsNullOrWhiteSpace(resolutionCode) ? "RESOLVED" : resolutionCode.Trim().ToUpperInvariant();
    }

    public void ApplyProviderSettlement(decimal settledAmount, decimal feeAmount, decimal netAmount, string? providerReference, string? notes, string settlementStatusCode)
    {
        if (settledAmount < 0m || feeAmount < 0m || netAmount < 0m)
        {
            throw new InvalidOperationException("Payment settlement line monetary amounts cannot be negative.");
        }

        SettledAmount = settledAmount;
        FeeAmount = feeAmount;
        NetAmount = netAmount;
        ProviderReference = string.IsNullOrWhiteSpace(providerReference) ? ProviderReference : providerReference.Trim();
        Notes = string.IsNullOrWhiteSpace(notes) ? Notes : notes.Trim();
        SettlementStatusCode = string.IsNullOrWhiteSpace(settlementStatusCode) ? SettlementStatusCode : settlementStatusCode.Trim().ToUpperInvariant();
    }
}
