using CashLineERP.Contracts.IslamicFinance;
using CashLineERP.Application.IslamicFinance;
using CashLineERP.SharedKernel.IslamicFinance;

namespace CashLineERP.Application.IslamicFinance.Settlements;

public sealed class IslamicFinanceSettlementService : IIslamicFinanceSettlementService
{
    private readonly IIslamicFinanceSettlementRepository _repository;

    public IslamicFinanceSettlementService(IIslamicFinanceSettlementRepository repository)
    {
        _repository = repository;
    }

    public IReadOnlyCollection<IslamicFinanceSettlementResponse> GetSettlements(long? murabahaCaseId = null, string? statusCode = null) =>
        _repository.GetSettlements(murabahaCaseId, statusCode).Select(Map).ToArray();

    public IslamicFinanceSettlementResponse? GetSettlement(long settlementHeaderId)
    {
        var entry = _repository.GetSettlement(settlementHeaderId);
        return entry is null ? null : Map(entry);
    }

    public IslamicFinanceSettlementResponse CreateSettlement(CreateIslamicFinanceSettlementRequest request) =>
        Map(_repository.Create(new CreateIslamicFinanceSettlementCommand(
            request.SettlementNumber,
            request.MurabahaCaseId,
            request.SettlementDate,
            request.SettlementCurrencyCode,
            request.Lines.Select(line => new CreateIslamicFinanceSettlementLineCommand(line.MurabahaDisbursementId, line.SettledAmount)).ToArray())));

    public IslamicFinanceSettlementResponse SubmitSettlement(long settlementHeaderId, long actorUserId) =>
        Map(_repository.Submit(settlementHeaderId, actorUserId));

    public IslamicFinanceSettlementResponse ApproveSettlement(long settlementHeaderId, long actorUserId) =>
        Map(_repository.Approve(settlementHeaderId, actorUserId));

    public IslamicFinanceSettlementResponse CloseSettlement(long settlementHeaderId, long actorUserId) =>
        Map(_repository.Close(settlementHeaderId, actorUserId));

    public IReadOnlyCollection<IslamicFinanceLifecycleHistoryEntryResponse> GetSettlementHistory(long settlementHeaderId) =>
        _repository.GetSettlementHistory(settlementHeaderId).Select(Map).ToArray();

    public IslamicFinanceSettlementAuditResponse? GetSettlementAudit(long settlementHeaderId)
    {
        var entry = _repository.GetSettlementAudit(settlementHeaderId);
        return entry is null ? null : new IslamicFinanceSettlementAuditResponse(
            Map(entry.Settlement),
            entry.Events.Select(Map).ToArray());
    }

    private static IslamicFinanceSettlementResponse Map(IslamicFinanceSettlementDetailView entry) =>
        new()
        {
            Id = entry.SettlementHeaderId,
            SettlementNumber = entry.SettlementNumber,
            MurabahaCaseId = entry.MurabahaCaseId,
            FinancingRequestId = entry.FinancingRequestId,
            PartnerLenderId = entry.PartnerLenderId,
            FundingSourceMode = IslamicFinanceProductCatalog.NormalizeFundingSourceMode(entry.FundingSourceMode),
            SettlementDate = entry.SettlementDate,
            SettlementCurrencyCode = entry.SettlementCurrencyCode,
            TotalSettledAmount = entry.TotalSettledAmount,
            StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(entry.StatusCode),
            WorkflowInstanceId = entry.WorkflowInstanceId,
            CreatedAtUtc = entry.CreatedAtUtc,
            CreatedByUserId = entry.CreatedByUserId,
            SubmittedAtUtc = entry.SubmittedAtUtc,
            SubmittedByUserId = entry.SubmittedByUserId,
            ApprovedAtUtc = entry.ApprovedAtUtc,
            ApprovedByUserId = entry.ApprovedByUserId,
            ClosedAtUtc = entry.ClosedAtUtc,
            ClosedByUserId = entry.ClosedByUserId,
            UpdatedAtUtc = entry.UpdatedAtUtc,
            UpdatedByUserId = entry.UpdatedByUserId,
            Lines = entry.Lines.Select(Map).ToArray()
        };

    private static IslamicFinanceSettlementLineResponse Map(IslamicFinanceSettlementLineView entry) =>
        new()
        {
            Id = entry.SettlementLineId,
            SettlementHeaderId = entry.SettlementHeaderId,
            MurabahaDisbursementId = entry.MurabahaDisbursementId,
            DisbursementNumber = entry.DisbursementNumber,
            SettledAmount = entry.SettledAmount,
            StatusCode = entry.StatusCode,
            CreatedAtUtc = entry.CreatedAtUtc,
            CreatedByUserId = entry.CreatedByUserId,
            UpdatedAtUtc = entry.UpdatedAtUtc,
            UpdatedByUserId = entry.UpdatedByUserId
        };

    private static IslamicFinanceLifecycleHistoryEntryResponse Map(IslamicFinanceLifecycleHistoryEntryView entry) =>
        new(
            entry.EntityId,
            entry.EventCode,
            entry.SourceType,
            entry.SourceId,
            entry.ActorUserId,
            entry.Notes,
            entry.OccurredAtUtc);
}
