using CashLineERP.Domain.IslamicFinance.Disbursements;
using CashLineERP.Domain.IslamicFinance.Murabaha;
using CashLineERP.Domain.IslamicFinance.Requests;
using CashLineERP.Domain.IslamicFinance.Settlements;
using CashLineERP.Domain.IslamicFinance.Shariah;
using CashLineERP.SharedKernel.IslamicFinance;

namespace CashLineERP.Infrastructure.Persistence.Repositories.IslamicFinance;

internal static class IslamicFinanceLifecycleOutboxWriter
{
    public static void EnqueueFinancingRequestEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceRequest request,
        string eventType,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.FinancingRequestAggregateType,
            aggregateId: request.Id,
            eventType: eventType,
            payload: new
            {
                request.Id,
                request.RequestNumber,
                request.CustomerPartyId,
                request.ProductProfileId,
                request.FacilityId,
                FundingSourceMode = IslamicFinanceProductCatalog.NormalizeFundingSourceMode(request.FundingSourceMode),
                request.SourceDocumentType,
                request.SourceDocumentId,
                request.TransactionCurrencyCode,
                request.RequestedAmount,
                StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(request.StatusCode),
                request.AssignedPartnerLenderId,
                request.ShariahReviewCaseId
            },
            actorUserId: actorUserId,
            correlationKey: request.RequestNumber);
    }

    public static void EnqueueFinancingDecisionEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceDecision decision,
        string requestNumber,
        string eventType,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.FinancingDecisionAggregateType,
            aggregateId: decision.Id,
            eventType: eventType,
            payload: new
            {
                decision.Id,
                decision.FinancingRequestId,
                DecisionCode = IslamicFinanceDecisionCatalog.NormalizeDecisionCode(decision.DecisionCode),
                decision.DecisionNotes,
                decision.DecidingPartyId,
                decision.PartnerLenderId,
                StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(decision.StatusCode)
            },
            actorUserId: actorUserId,
            correlationKey: requestNumber);
    }

    public static void EnqueueShariahReviewEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceShariahReviewCase reviewCase,
        string eventType,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.ShariahReviewAggregateType,
            aggregateId: reviewCase.Id,
            eventType: eventType,
            payload: new
            {
                reviewCase.Id,
                reviewCase.ReviewCaseNumber,
                reviewCase.ProductProfileId,
                reviewCase.FinancingRequestId,
                ReviewReasonCode = IslamicFinanceGovernanceCatalog.NormalizeReasonCode(reviewCase.ReviewReasonCode),
                ReviewOutcomeCode = string.IsNullOrWhiteSpace(reviewCase.ReviewOutcomeCode)
                    ? null
                    : IslamicFinanceShariahOutcomeCatalog.NormalizeOutcomeCode(reviewCase.ReviewOutcomeCode),
                reviewCase.ReviewNotes,
                StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(reviewCase.StatusCode)
            },
            actorUserId: actorUserId,
            correlationKey: reviewCase.ReviewCaseNumber);
    }

    public static void EnqueueMurabahaCaseEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceMurabahaCase murabahaCase,
        string eventType,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.MurabahaCaseAggregateType,
            aggregateId: murabahaCase.Id,
            eventType: eventType,
            payload: new
            {
                murabahaCase.Id,
                murabahaCase.CaseNumber,
                murabahaCase.FinancingRequestId,
                murabahaCase.CustomerPartyId,
                murabahaCase.PartnerLenderId,
                murabahaCase.SupplierPartyId,
                murabahaCase.ProductProfileId,
                murabahaCase.ContractTemplateId,
                murabahaCase.TransactionCurrencyCode,
                murabahaCase.PurchaseCostAmount,
                murabahaCase.ProfitAmount,
                murabahaCase.SalePriceAmount,
                StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(murabahaCase.StatusCode)
            },
            actorUserId: actorUserId,
            correlationKey: murabahaCase.CaseNumber);
    }

    public static void EnqueueMurabahaScheduleGeneratedEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceMurabahaCase murabahaCase,
        int installmentCount,
        DateOnly firstDueDate,
        int installmentIntervalMonths,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.MurabahaCaseAggregateType,
            aggregateId: murabahaCase.Id,
            eventType: IslamicFinanceIntegrationEventCatalog.MurabahaScheduleGenerated,
            payload: new
            {
                murabahaCase.Id,
                murabahaCase.CaseNumber,
                installmentCount,
                firstDueDate,
                installmentIntervalMonths,
                murabahaCase.TransactionCurrencyCode,
                murabahaCase.SalePriceAmount
            },
            actorUserId: actorUserId,
            correlationKey: murabahaCase.CaseNumber);
    }

    public static void EnqueueSettlementEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceMurabahaDisbursement disbursement,
        string eventType,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.SettlementAggregateType,
            aggregateId: disbursement.Id,
            eventType: eventType,
            payload: new
            {
                disbursement.Id,
                disbursement.DisbursementNumber,
                disbursement.MurabahaCaseId,
                disbursement.CustomerPartyId,
                disbursement.PartnerLenderId,
                disbursement.SupplierPartyId,
                FundingSourceMode = IslamicFinanceProductCatalog.NormalizeFundingSourceMode(disbursement.FundingSourceMode),
                TargetType = IslamicFinanceDisbursementCatalog.NormalizeTargetType(disbursement.TargetType),
                disbursement.TransactionCurrencyCode,
                disbursement.InstructedAmount,
                disbursement.ExecutedAmount,
                disbursement.PlannedExecutionDate,
                StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(disbursement.StatusCode),
                disbursement.ExecutionReferenceNumber,
                disbursement.SuspensionReasonCode
            },
            actorUserId: actorUserId,
            correlationKey: disbursement.DisbursementNumber);
    }

    public static void EnqueueSettlementEvent(
        CashLineErpDbContext dbContext,
        IslamicFinanceSettlementHeader settlement,
        IReadOnlyCollection<long> disbursementIds,
        string eventType,
        long? actorUserId)
    {
        OutboxEventWriter.Enqueue(
            dbContext,
            sourceModuleCode: IslamicFinanceIntegrationEventCatalog.SourceModuleCode,
            aggregateType: IslamicFinanceIntegrationEventCatalog.SettlementAggregateType,
            aggregateId: settlement.Id,
            eventType: eventType,
            payload: new
            {
                settlement.Id,
                settlement.SettlementNumber,
                settlement.MurabahaCaseId,
                settlement.FinancingRequestId,
                settlement.PartnerLenderId,
                FundingSourceMode = IslamicFinanceProductCatalog.NormalizeFundingSourceMode(settlement.FundingSourceMode),
                settlement.SettlementDate,
                settlement.SettlementCurrencyCode,
                settlement.TotalSettledAmount,
                StatusCode = IslamicFinanceWorkflowCatalog.NormalizeStatusCode(settlement.StatusCode),
                DisbursementIds = disbursementIds.Order().ToArray()
            },
            actorUserId: actorUserId,
            correlationKey: settlement.SettlementNumber);
    }
}
