using CashLineERP.Contracts.Parties;

namespace CashLineERP.Application.Parties;

public sealed class PartyOnboardingService : IPartyOnboardingService
{
    private readonly IBusinessPartyRepository _businessPartyRepository;

    public PartyOnboardingService(IBusinessPartyRepository businessPartyRepository)
    {
        _businessPartyRepository = businessPartyRepository;
    }

    public IReadOnlyCollection<BusinessPartyResponse> GetParties(string? partyType = null)
    {
        return _businessPartyRepository.GetParties(partyType)
            .Select(Map)
            .ToArray();
    }

    public BusinessPartyResponse CreateParty(CreateBusinessPartyRequest request)
    {
        var party = _businessPartyRepository.Create(new CreateBusinessPartyCommand(
            request.PartyCode,
            request.PartyName,
            request.PartyType,
            request.CountryCode,
            request.FirmNationalId,
            request.TaxRegistrationNumber,
            request.TaxBranchCode,
            request.Email,
            request.MobileNumber,
            request.AddressLine1,
            request.CreditLimitAmount,
            request.CreditTermsDays,
            request.IsCreditHoldEnabled,
            request.CreditHoldReason));

        return Map(party);
    }

    public BusinessPartyResponse SetFirmNationalId(long partyId, string? firmNationalId, long actorUserId)
    {
        var party = _businessPartyRepository.SetFirmNationalId(partyId, firmNationalId, actorUserId);
        return Map(party);
    }

    public IReadOnlyCollection<BusinessPartyResponse> GetActiveClientsMissingFirmNationalId()
    {
        return _businessPartyRepository.GetActiveClientsMissingFirmNationalId()
            .Select(Map)
            .ToArray();
    }

    public IReadOnlyCollection<BusinessPartyComplianceDocumentResponse> GetComplianceDocuments(long partyId) =>
        _businessPartyRepository.GetComplianceDocuments(partyId)
            .Select(document => new BusinessPartyComplianceDocumentResponse(
                document.DocumentLinkId,
                document.PartyId,
                document.DocumentType,
                document.FileName,
                document.StorageReference,
                document.ContentType,
                document.FileSizeBytes,
                document.UploadedAtUtc,
                document.UploadedByUserId))
            .ToArray();

    public BusinessPartyComplianceDocumentResponse RecordComplianceDocument(long actorUserId, long partyId, RecordBusinessPartyComplianceDocumentRequest request)
    {
        var document = _businessPartyRepository.RecordComplianceDocument(actorUserId, new RecordBusinessPartyComplianceDocumentCommand(
            partyId,
            request.DocumentType,
            request.FileName,
            request.StorageReference,
            request.ContentType,
            request.FileSizeBytes));

        return new BusinessPartyComplianceDocumentResponse(
            document.DocumentLinkId,
            document.PartyId,
            document.DocumentType,
            document.FileName,
            document.StorageReference,
            document.ContentType,
            document.FileSizeBytes,
            document.UploadedAtUtc,
            document.UploadedByUserId);
    }

    private static BusinessPartyResponse Map(BusinessPartyView party) =>
        new(
            party.PartyId,
            party.PartyCode,
            party.PartyName,
            party.PartyType,
            party.CountryCode,
            party.FirmNationalId,
            party.TaxRegistrationNumber,
            party.Email,
            party.MobileNumber,
            party.CreditLimitAmount,
            party.CreditTermsDays,
            party.IsCreditHoldEnabled,
            party.CreditHoldReason,
            party.IsActive);
}
