using CashLineERP.Contracts.Tax;

namespace CashLineERP.Application.Tax;

public sealed class StatutoryTaxService : IStatutoryTaxService
{
    private readonly IStatutoryTaxRepository _repository;

    public StatutoryTaxService(IStatutoryTaxRepository repository)
    {
        _repository = repository;
    }

    public DocumentTaxSummaryResponse? GetAccountsPayableBillTaxSummary(long accountsPayableBillId)
    {
        var summary = _repository.GetAccountsPayableBillTaxSummary(accountsPayableBillId);
        return summary is null ? null : Map(summary);
    }

    public DocumentTaxSummaryResponse? GetAccountsReceivableInvoiceTaxSummary(long accountsReceivableInvoiceId)
    {
        var summary = _repository.GetAccountsReceivableInvoiceTaxSummary(accountsReceivableInvoiceId);
        return summary is null ? null : Map(summary);
    }

    public DocumentVatBreakdownExportResponse? GetAccountsPayableBillVatBreakdownExport(long accountsPayableBillId)
    {
        var export = _repository.GetAccountsPayableBillVatBreakdownExport(accountsPayableBillId);
        return export is null ? null : Map(export);
    }

    public DocumentVatBreakdownExportResponse? GetAccountsReceivableInvoiceVatBreakdownExport(long accountsReceivableInvoiceId)
    {
        var export = _repository.GetAccountsReceivableInvoiceVatBreakdownExport(accountsReceivableInvoiceId);
        return export is null ? null : Map(export);
    }

    public DocumentWithholdingSummaryResponse? GetAccountsPayableBillWithholdingSummary(long accountsPayableBillId)
    {
        var summary = _repository.GetAccountsPayableBillWithholdingSummary(accountsPayableBillId);
        return summary is null ? null : Map(summary);
    }

    public DocumentWithholdingSummaryResponse? GetAccountsReceivableInvoiceWithholdingSummary(long accountsReceivableInvoiceId)
    {
        var summary = _repository.GetAccountsReceivableInvoiceWithholdingSummary(accountsReceivableInvoiceId);
        return summary is null ? null : Map(summary);
    }

    public DocumentWithholdingExportResponse? GetAccountsPayableBillWithholdingExport(long accountsPayableBillId)
    {
        var export = _repository.GetAccountsPayableBillWithholdingExport(accountsPayableBillId);
        return export is null ? null : Map(export);
    }

    public DocumentWithholdingExportResponse? GetAccountsReceivableInvoiceWithholdingExport(long accountsReceivableInvoiceId)
    {
        var export = _repository.GetAccountsReceivableInvoiceWithholdingExport(accountsReceivableInvoiceId);
        return export is null ? null : Map(export);
    }

    public StatutoryEvidenceExportResponse? GetAccountsPayableBillStatutoryEvidenceExport(long accountsPayableBillId)
    {
        var export = _repository.GetAccountsPayableBillStatutoryEvidenceExport(accountsPayableBillId);
        return export is null ? null : Map(export);
    }

    public StatutoryEvidenceExportResponse? GetAccountsReceivableInvoiceStatutoryEvidenceExport(long accountsReceivableInvoiceId)
    {
        var export = _repository.GetAccountsReceivableInvoiceStatutoryEvidenceExport(accountsReceivableInvoiceId);
        return export is null ? null : Map(export);
    }

    public FinanceReviewExportPackageResponse? GetAccountsPayableBillFinanceReviewPackage(long accountsPayableBillId)
    {
        var vatExport = GetAccountsPayableBillVatBreakdownExport(accountsPayableBillId);
        var withholdingExport = GetAccountsPayableBillWithholdingExport(accountsPayableBillId);
        var evidenceExport = GetAccountsPayableBillStatutoryEvidenceExport(accountsPayableBillId);
        if (vatExport is null || withholdingExport is null || evidenceExport is null)
        {
            return null;
        }

        return BuildPackage(vatExport.DocumentType, vatExport.DocumentId, vatExport.DocumentNumber, vatExport.ExportedAtUtc, vatExport, withholdingExport, evidenceExport);
    }

    public FinanceReviewExportPackageResponse? GetAccountsReceivableInvoiceFinanceReviewPackage(long accountsReceivableInvoiceId)
    {
        var vatExport = GetAccountsReceivableInvoiceVatBreakdownExport(accountsReceivableInvoiceId);
        var withholdingExport = GetAccountsReceivableInvoiceWithholdingExport(accountsReceivableInvoiceId);
        var evidenceExport = GetAccountsReceivableInvoiceStatutoryEvidenceExport(accountsReceivableInvoiceId);
        if (vatExport is null || withholdingExport is null || evidenceExport is null)
        {
            return null;
        }

        return BuildPackage(vatExport.DocumentType, vatExport.DocumentId, vatExport.DocumentNumber, vatExport.ExportedAtUtc, vatExport, withholdingExport, evidenceExport);
    }

    private static DocumentTaxSummaryResponse Map(DocumentTaxSummaryView summary) =>
        new(
            summary.DocumentType,
            summary.DocumentId,
            summary.DocumentNumber,
            summary.DocumentDate,
            summary.TaxDate,
            summary.CurrencyCode,
            summary.SubtotalAmount,
            summary.TaxAmount,
            summary.TotalAmount,
            summary.IsStatutoryReady,
            summary.ValidationMessages,
            summary.Breakdowns.Select(breakdown => new DocumentTaxBreakdownResponse(
                breakdown.TaxCode,
                breakdown.TaxCategory,
                breakdown.TaxRate,
                breakdown.TaxableAmount,
                breakdown.TaxAmount,
                breakdown.TotalAmount,
                breakdown.LineCount)).ToArray());

    private static DocumentVatBreakdownExportResponse Map(DocumentVatBreakdownExportView export) =>
        new(
            export.DocumentType,
            export.DocumentId,
            export.DocumentNumber,
            export.DocumentDate,
            export.TaxDate,
            export.CurrencyCode,
            export.ExportedAtUtc,
            export.FileName,
            export.ContentType,
            export.ContentText,
            export.Breakdowns.Select(breakdown => new DocumentTaxBreakdownResponse(
                breakdown.TaxCode,
                breakdown.TaxCategory,
                breakdown.TaxRate,
                breakdown.TaxableAmount,
                breakdown.TaxAmount,
                breakdown.TotalAmount,
                breakdown.LineCount)).ToArray());

    private static DocumentWithholdingSummaryResponse Map(DocumentWithholdingSummaryView summary) =>
        new(
            summary.DocumentType,
            summary.DocumentId,
            summary.DocumentNumber,
            summary.DocumentDate,
            summary.TaxDate,
            summary.CurrencyCode,
            summary.SubtotalAmount,
            summary.DocumentTotalAmount,
            summary.TotalWithholdingAmount,
            summary.NetSettlementAmount,
            summary.IsWithholdingReady,
            summary.ValidationMessages,
            summary.Breakdowns.Select(breakdown => new DocumentWithholdingBreakdownResponse(
                breakdown.WithholdingCode,
                breakdown.WithholdingCategory,
                breakdown.WithholdingRate,
                breakdown.BaseAmount,
                breakdown.WithholdingAmount,
                breakdown.LineCount)).ToArray());

    private static DocumentWithholdingExportResponse Map(DocumentWithholdingExportView export) =>
        new(
            export.DocumentType,
            export.DocumentId,
            export.DocumentNumber,
            export.DocumentDate,
            export.TaxDate,
            export.CurrencyCode,
            export.SubtotalAmount,
            export.DocumentTotalAmount,
            export.TotalWithholdingAmount,
            export.NetSettlementAmount,
            export.ExportedAtUtc,
            export.FileName,
            export.ContentType,
            export.ContentText,
            export.Breakdowns.Select(breakdown => new DocumentWithholdingBreakdownResponse(
                breakdown.WithholdingCode,
                breakdown.WithholdingCategory,
                breakdown.WithholdingRate,
                breakdown.BaseAmount,
                breakdown.WithholdingAmount,
                breakdown.LineCount)).ToArray());

    private static StatutoryEvidenceExportResponse Map(StatutoryEvidenceExportView export) =>
        new(
            export.DocumentType,
            export.DocumentId,
            export.DocumentNumber,
            export.DocumentDate,
            export.TaxDate,
            export.CurrencyCode,
            export.CounterpartyCode,
            export.CounterpartyName,
            export.CounterpartyType,
            export.CounterpartyTaxRegistrationNumber,
            export.BranchCode,
            export.BranchName,
            export.BranchTaxBranchCode,
            export.IsStatutoryReady,
            export.ExportedAtUtc,
            export.FileName,
            export.ContentType,
            export.ContentText,
            export.ValidationMessages);

    private static FinanceReviewExportPackageResponse BuildPackage(
        string documentType,
        long documentId,
        string documentNumber,
        DateTime exportedAtUtc,
        DocumentVatBreakdownExportResponse vatExport,
        DocumentWithholdingExportResponse withholdingExport,
        StatutoryEvidenceExportResponse evidenceExport) =>
        new(
            documentType,
            documentId,
            documentNumber,
            exportedAtUtc,
            $"{documentNumber}_finance_review_package.zip",
            [
                new FinanceReviewExportPackageEntryResponse("VAT_BREAKDOWN", vatExport.FileName, vatExport.ContentType, vatExport.ContentText),
                new FinanceReviewExportPackageEntryResponse("WITHHOLDING", withholdingExport.FileName, withholdingExport.ContentType, withholdingExport.ContentText),
                new FinanceReviewExportPackageEntryResponse("STATUTORY_EVIDENCE", evidenceExport.FileName, evidenceExport.ContentType, evidenceExport.ContentText)
            ]);
}
