using CashLineERP.Contracts.Finance;

namespace CashLineERP.Application.Finance;

public sealed class SupplierAccountReconciliationService : ISupplierAccountReconciliationService
{
    private readonly ISupplierAccountReconciliationRepository _repository;

    public SupplierAccountReconciliationService(ISupplierAccountReconciliationRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<SupplierAccountReconciliationSummaryResponse> GetSummaries(DateOnly? asOfDate = null, long? supplierId = null, string? currencyCode = null)
    {
        var normalizedAsOfDate = asOfDate ?? DateOnly.FromDateTime(DateTime.UtcNow.Date);
        return _repository.GetSummaries(normalizedAsOfDate, supplierId, currencyCode)
            .Select(Map)
            .ToArray();
    }

    public SupplierAccountReconciliationResponse GetDetail(long supplierId, DateOnly? asOfDate = null, string? currencyCode = null)
    {
        var normalizedAsOfDate = asOfDate ?? DateOnly.FromDateTime(DateTime.UtcNow.Date);
        var detail = _repository.GetDetail(supplierId, normalizedAsOfDate, currencyCode);
        return new SupplierAccountReconciliationResponse(
            detail.SupplierId,
            detail.SupplierCode,
            detail.SupplierName,
            detail.AsOfDate,
            detail.CurrencyCode,
            detail.LastStatementId,
            detail.LastStatementNumber,
            detail.LastStatementGeneratedAtUtc,
            detail.LastStatementClosingBalanceAmount,
            detail.CurrentBalanceAmount,
            detail.OpenPayableAmount,
            detail.OverduePayableAmount,
            detail.UnappliedPaymentAmount,
            detail.OnHoldBillCount,
            detail.DifferenceAmount,
            detail.Lines.Select(Map).ToArray());
    }

    private static SupplierAccountReconciliationSummaryResponse Map(SupplierAccountReconciliationSummaryView summary) =>
        new(
            summary.SupplierId,
            summary.SupplierCode,
            summary.SupplierName,
            summary.AsOfDate,
            summary.CurrencyCode,
            summary.LastStatementId,
            summary.LastStatementNumber,
            summary.LastStatementGeneratedAtUtc,
            summary.LastStatementClosingBalanceAmount,
            summary.CurrentBalanceAmount,
            summary.OpenPayableAmount,
            summary.OverduePayableAmount,
            summary.UnappliedPaymentAmount,
            summary.OnHoldBillCount,
            summary.DifferenceAmount);

    private static SupplierAccountReconciliationLineResponse Map(SupplierAccountReconciliationLineView line) =>
        new(
            line.EntryType,
            line.DocumentType,
            line.DocumentId,
            line.DocumentNumber,
            line.BusinessDate,
            line.DueDate,
            line.CurrencyCode,
            line.ChargeAmount,
            line.SettlementAmount,
            line.RunningBalanceAmount,
            line.StatusCode,
            line.SecondaryStatus,
            line.ReferenceText);
}
