using CashLineERP.Domain.Common;
using CashLineERP.SharedKernel.IslamicFinance;
using System.ComponentModel.DataAnnotations.Schema;

namespace CashLineERP.Domain.IslamicFinance.Accounting;

public sealed class IslamicFinanceAccountingHook : Entity
{
    public long Id { get; private set; }
    public string SourceEntityType { get; private set; } = string.Empty;
    public long SourceEntityId { get; private set; }
    public string FundingSourceMode { get; private set; } = IslamicFinanceProductCatalog.ToCode(IslamicFinanceFundingSourceMode.Partner);
    public string ProductType { get; private set; } = IslamicFinanceProductCatalog.ToCode(IslamicFinanceProductType.Murabaha);
    public long CustomerPartyId { get; private set; }
    public long? PartnerLenderId { get; private set; }
    public long? GeneralLedgerBatchId { get; private set; }
    public string PostingStatusCode { get; private set; } = IslamicFinanceWorkflowCatalog.Draft;
    [NotMapped]
    public IslamicFinanceFundingSourceMode FundingSourceModeValue => IslamicFinanceProductCatalog.ParseFundingSourceMode(FundingSourceMode);
    [NotMapped]
    public IslamicFinanceProductType ProductTypeValue => IslamicFinanceProductCatalog.ParseProductType(ProductType);
    [NotMapped]
    public IslamicFinanceLifecycleState PostingLifecycleState => IslamicFinanceWorkflowCatalog.ParseStatusCode(PostingStatusCode);

    public IslamicFinanceAccountingHook(
        string sourceEntityType,
        long sourceEntityId,
        IslamicFinanceFundingSourceMode fundingSourceMode,
        IslamicFinanceProductType productType,
        long customerPartyId,
        long? partnerLenderId)
    {
        if (string.IsNullOrWhiteSpace(sourceEntityType))
        {
            throw new InvalidOperationException("Islamic Finance accounting hook source entity type is required.");
        }

        if (sourceEntityId <= 0)
        {
            throw new InvalidOperationException("Islamic Finance accounting hook source entity identifier must be positive.");
        }

        if (customerPartyId <= 0)
        {
            throw new InvalidOperationException("Islamic Finance accounting hook customer party identifier must be positive.");
        }

        if (partnerLenderId.HasValue && partnerLenderId.Value <= 0)
        {
            throw new InvalidOperationException("Islamic Finance accounting hook partner lender identifier must be positive when provided.");
        }

        SourceEntityType = sourceEntityType.Trim().ToUpperInvariant();
        SourceEntityId = sourceEntityId;
        FundingSourceMode = IslamicFinanceProductCatalog.ToCode(fundingSourceMode);
        ProductType = IslamicFinanceProductCatalog.ToCode(productType);
        CustomerPartyId = customerPartyId;
        PartnerLenderId = partnerLenderId;
    }

    private IslamicFinanceAccountingHook()
    {
    }

    public void LinkGeneralLedgerBatch(long generalLedgerBatchId, long actorUserId)
    {
        if (generalLedgerBatchId <= 0)
        {
            throw new InvalidOperationException("Islamic Finance accounting hook general-ledger batch identifier must be positive.");
        }

        if (GeneralLedgerBatchId.HasValue && GeneralLedgerBatchId.Value == generalLedgerBatchId)
        {
            return;
        }

        if (GeneralLedgerBatchId.HasValue && GeneralLedgerBatchId.Value != generalLedgerBatchId)
        {
            throw new InvalidOperationException("Islamic Finance accounting hook is already linked to a different general-ledger batch.");
        }

        GeneralLedgerBatchId = generalLedgerBatchId;
        PostingStatusCode = IslamicFinanceWorkflowCatalog.Active;
        Touch(actorUserId);
    }
}
