using CashLineERP.Domain.Common;

namespace CashLineERP.Domain.Finance;

public sealed class ForeignExchangeQuote : Entity
{
    public long Id { get; private set; }
    public string QuoteNumber { get; private set; } = string.Empty;
    public long IntegrationEndpointId { get; private set; }
    public DateOnly QuoteDate { get; private set; }
    public string BaseCurrencyCode { get; private set; } = "EGP";
    public string CurrencyCode { get; private set; } = "USD";
    public decimal RateToBase { get; private set; }
    public string? SourceBatchReference { get; private set; }
    public string? ExternalQuoteReference { get; private set; }
    public string? Notes { get; private set; }
    public DateTime IngestedAtUtc { get; private set; }
    public long IngestedByUserId { get; private set; }

    public ForeignExchangeQuote(
        string quoteNumber,
        long integrationEndpointId,
        DateOnly quoteDate,
        string baseCurrencyCode,
        string currencyCode,
        decimal rateToBase,
        string? sourceBatchReference,
        string? externalQuoteReference,
        string? notes,
        long ingestedByUserId)
    {
        if (string.IsNullOrWhiteSpace(quoteNumber))
        {
            throw new InvalidOperationException("FX quote number is required.");
        }

        if (integrationEndpointId <= 0)
        {
            throw new InvalidOperationException("FX quote requires a valid integration endpoint.");
        }

        var normalizedBaseCurrencyCode = NormalizeCurrencyCode(baseCurrencyCode);
        var normalizedCurrencyCode = NormalizeCurrencyCode(currencyCode);

        if (string.Equals(normalizedBaseCurrencyCode, normalizedCurrencyCode, StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("FX quote currency cannot equal the base currency.");
        }

        if (rateToBase <= 0m)
        {
            throw new InvalidOperationException("FX quote rate to base must be greater than zero.");
        }

        QuoteNumber = quoteNumber.Trim().ToUpperInvariant();
        IntegrationEndpointId = integrationEndpointId;
        QuoteDate = quoteDate;
        BaseCurrencyCode = normalizedBaseCurrencyCode;
        CurrencyCode = normalizedCurrencyCode;
        RateToBase = rateToBase;
        SourceBatchReference = NormalizeOptional(sourceBatchReference);
        ExternalQuoteReference = NormalizeOptional(externalQuoteReference);
        Notes = NormalizeOptional(notes);
        IngestedAtUtc = DateTime.UtcNow;
        IngestedByUserId = ingestedByUserId;
    }

    private ForeignExchangeQuote()
    {
    }

    private static string NormalizeCurrencyCode(string currencyCode)
    {
        var normalized = currencyCode?.Trim().ToUpperInvariant();
        if (string.IsNullOrWhiteSpace(normalized))
        {
            throw new InvalidOperationException("FX quote currency code is required.");
        }

        return normalized;
    }

    private static string? NormalizeOptional(string? value) =>
        string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
