using CashLineERP.Application.Documents;
using CashLineERP.Application.IslamicFinance.Murabaha;
using CashLineERP.SharedKernel.IslamicFinance;
using Microsoft.EntityFrameworkCore;

namespace CashLineERP.Infrastructure.Persistence.Repositories.IslamicFinance;

public sealed class IslamicFinanceMurabahaAssetEvidenceRepository : IIslamicFinanceMurabahaAssetEvidenceRepository
{
    private readonly CashLineErpDbContext _dbContext;
    private readonly IDocumentStorageRepository _documentStorageRepository;

    public IslamicFinanceMurabahaAssetEvidenceRepository(
        CashLineErpDbContext dbContext,
        IDocumentStorageRepository documentStorageRepository)
    {
        _dbContext = dbContext;
        _documentStorageRepository = documentStorageRepository;
    }

    public IReadOnlyCollection<DocumentAttachmentDetailView> GetEvidence(long murabahaAssetId, string? attachmentCategoryCode = null)
    {
        EnsureAssetExists(murabahaAssetId);
        return _documentStorageRepository.GetDocuments(
            IslamicFinanceDocumentCatalog.ModuleCode,
            IslamicFinanceDocumentCatalog.MurabahaAssetEntityName,
            murabahaAssetId,
            attachmentCategoryCode: attachmentCategoryCode);
    }

    public DocumentAttachmentDetailView? GetEvidenceDocument(long murabahaAssetId, long documentLinkId)
    {
        EnsureAssetExists(murabahaAssetId);
        var document = _documentStorageRepository.GetDocument(documentLinkId);
        if (document is null)
        {
            return null;
        }

        return IsMurabahaAssetEvidence(document, murabahaAssetId)
            ? document
            : null;
    }

    public DocumentAttachmentDetailView CreateEvidence(long murabahaAssetId, long actorUserId, AttachIslamicFinanceMurabahaAssetEvidenceCommand command)
    {
        EnsureAssetExists(murabahaAssetId);

        return _documentStorageRepository.CreateDocument(actorUserId, new CreateDocumentAttachmentCommand(
            IslamicFinanceDocumentCatalog.ModuleCode,
            IslamicFinanceDocumentCatalog.MurabahaAssetEntityName,
            murabahaAssetId,
            command.DocumentType,
            command.AttachmentCategoryCode,
            command.FileName,
            command.StorageReference,
            command.StorageProviderCode,
            command.ContentType,
            command.FileSizeBytes,
            command.ChecksumText,
            command.RetentionUntilUtc));
    }

    private void EnsureAssetExists(long murabahaAssetId)
    {
        if (!_dbContext.IslamicFinanceMurabahaAssets
            .AsNoTracking()
            .Any(entry => entry.Id == murabahaAssetId))
        {
            throw new InvalidOperationException("Islamic Finance Murabaha asset evidence requires a valid Murabaha asset.");
        }
    }

    private static bool IsMurabahaAssetEvidence(DocumentAttachmentDetailView document, long murabahaAssetId) =>
        string.Equals(document.ModuleCode, IslamicFinanceDocumentCatalog.ModuleCode, StringComparison.OrdinalIgnoreCase)
        && string.Equals(document.EntityName, IslamicFinanceDocumentCatalog.MurabahaAssetEntityName, StringComparison.OrdinalIgnoreCase)
        && document.EntityId == murabahaAssetId;
}
