import { format, startOfMonth } from 'date-fns';
import { EntryType, pcnGenerator } from '../../../../../pcn874-generator/src/index.js';
import { dateToTimelessDateString, idValidator, yearMonthValidator, } from '../../../shared/helpers/index.js';
import { BusinessesProvider } from '../../financial-entities/providers/businesses.provider.js';
import { getVatRecords } from '../resolvers/get-vat-records.resolver.js';
export const getHeaderDataFromRecords = (transactions, licensedDealerId, reportMonth = '', generationDate) => {
    let derivedReportMonth = reportMonth;
    let taxableSalesAmount = 0;
    let taxableSalesVat = 0;
    let salesRecordCount = 0;
    let zeroValOrExemptSalesCount = 0;
    let otherInputsVat = 0;
    let equipmentInputsVat = 0;
    let inputsCount = 0;
    for (const t of transactions) {
        const invoiceSumFactor = t.invoiceSum >= 0 ? 1 : -1;
        switch (t.entryType) {
            case EntryType.SALE_REGULAR: {
                taxableSalesVat += t.totalVat * invoiceSumFactor;
                taxableSalesAmount += t.invoiceSum;
                salesRecordCount += 1;
                break;
            }
            case EntryType.SALE_UNIDENTIFIED_CUSTOMER: {
                if (t.totalVat === 0) {
                    zeroValOrExemptSalesCount += t.invoiceSum;
                }
                else {
                    taxableSalesVat += t.totalVat * invoiceSumFactor;
                    taxableSalesAmount += t.invoiceSum;
                }
                salesRecordCount += 1;
                break;
            }
            case EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT: {
                salesRecordCount += 1;
                zeroValOrExemptSalesCount += t.invoiceSum;
                break;
            }
            case EntryType.INPUT_REGULAR: {
                if (t.isProperty) {
                    equipmentInputsVat += t.totalVat * invoiceSumFactor;
                }
                else {
                    otherInputsVat += t.totalVat * invoiceSumFactor;
                }
                inputsCount += 1;
                break;
            }
            case EntryType.INPUT_PETTY_CASH: {
                if (t.isProperty) {
                    equipmentInputsVat += t.totalVat * invoiceSumFactor;
                }
                else {
                    otherInputsVat += t.totalVat * invoiceSumFactor;
                }
                inputsCount += 1;
                break;
            }
            default: {
                console.debug(`Transaction EntryType  ${t.entryType} is not implemented yet`);
            }
        }
        if (t.invoiceDate.substring(0, 6) > derivedReportMonth) {
            derivedReportMonth = t.invoiceDate.substring(0, 6);
        }
    }
    const totalVat = taxableSalesVat - otherInputsVat - equipmentInputsVat;
    const header = {
        licensedDealerId,
        reportMonth: reportMonth || derivedReportMonth,
        generationDate,
        taxableSalesAmount,
        taxableSalesVat,
        salesRecordCount,
        zeroValOrExemptSalesCount,
        otherInputsVat,
        equipmentInputsVat,
        inputsCount,
        totalVat,
    };
    return header;
};
export const getEntryTypeByRecord = (entry) => {
    if (entry.pcn874RecordType) {
        switch (entry.pcn874RecordType) {
            case EntryType.SALE_REGULAR:
                return EntryType.SALE_REGULAR;
            case EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT:
                return EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT;
            case EntryType.INPUT_REGULAR:
                return EntryType.INPUT_REGULAR;
            case EntryType.INPUT_PETTY_CASH:
                return EntryType.INPUT_PETTY_CASH;
            case EntryType.SALE_SELF_INVOICE:
                return EntryType.SALE_SELF_INVOICE;
            case EntryType.SALE_EXPORT:
                return EntryType.SALE_EXPORT;
            case EntryType.SALE_PALESTINIAN_CUSTOMER:
                return EntryType.SALE_PALESTINIAN_CUSTOMER;
            case EntryType.SALE_ZERO_OR_EXEMPT:
                return EntryType.SALE_ZERO_OR_EXEMPT;
            case EntryType.SALE_UNIDENTIFIED_CUSTOMER:
                return EntryType.SALE_UNIDENTIFIED_CUSTOMER;
            case EntryType.INPUT_IMPORT:
                return EntryType.INPUT_IMPORT;
            case EntryType.INPUT_PALESTINIAN_SUPPLIER:
                return EntryType.INPUT_PALESTINIAN_SUPPLIER;
            case EntryType.INPUT_SINGLE_DOC_BY_LAW:
                return EntryType.INPUT_SINGLE_DOC_BY_LAW;
            case EntryType.INPUT_SELF_INVOICE:
                return EntryType.INPUT_SELF_INVOICE;
            default:
                throw new Error(`Unhandled PCN874 Record Type: ${entry.pcn874RecordType}`);
        }
    }
    if (entry.isExpense) {
        return EntryType.INPUT_REGULAR;
    }
    if ((entry.vatNumber ?? 0) === 0) {
        if (Number(entry.foreignVatAfterDeduction ?? 0) === 0 && (entry.localVat ?? 0) === 0) {
            return EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT;
        }
        return EntryType.SALE_UNIDENTIFIED_CUSTOMER;
    }
    if (Number(entry.foreignVatAfterDeduction ?? 0) === 0 && (entry.localVat ?? 0) === 0) {
        return EntryType.SALE_ZERO_OR_EXEMPT;
    }
    return EntryType.SALE_REGULAR;
};
const NO_VAT_ID_ENTRIES = [
    EntryType.SALE_UNIDENTIFIED_CUSTOMER,
    EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT,
    EntryType.INPUT_PETTY_CASH,
];
// TODO: migrate helper functions to PCN874 generator
export function getVatIdForTransaction(t) {
    if (t.pcn874RecordType && NO_VAT_ID_ENTRIES.includes(t.pcn874RecordType)) {
        return '0';
    }
    if (!t.vatNumber && t.pcn874RecordType === EntryType.INPUT_REGULAR) {
        return '999999999';
    }
    return t.vatNumber ?? '0';
}
export function getReferenceForTransaction(t) {
    if (t.pcn874RecordType === EntryType.INPUT_IMPORT) {
        return '0';
    }
    if (t.pcn874RecordType === EntryType.INPUT_PETTY_CASH) {
        return '1';
    }
    if (t.documentSerial) {
        return t.documentSerial;
    }
    if (t.pcn874RecordType === EntryType.SALE_UNIDENTIFIED_CUSTOMER ||
        t.pcn874RecordType === EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT) {
        return '1';
    }
    return '0';
}
export function getTotalVAT(t) {
    if (t.pcn874RecordType === EntryType.SALE_ZERO_OR_EXEMPT ||
        t.pcn874RecordType === EntryType.SALE_UNIDENTIFIED_ZERO_OR_EXEMPT ||
        t.pcn874RecordType === EntryType.SALE_EXPORT) {
        return 0;
    }
    return Math.round(Math.abs(Number(t.roundedVATToAdd ?? 0)));
}
const transactionsFromVatReportRecords = (vatRecords) => {
    const transactions = [];
    for (const t of vatRecords) {
        if (!t.documentDate) {
            console.debug(`Document ${t.documentId} has no tax_invoice_date. Skipping it.`);
            continue;
        }
        const entryType = getEntryTypeByRecord(t);
        const transaction = {
            entryType,
            vatId: getVatIdForTransaction(t),
            invoiceDate: format(new Date(t.documentDate), 'yyyyMMdd'),
            refGroup: '0000',
            refNumber: getReferenceForTransaction(t),
            totalVat: getTotalVAT(t),
            invoiceSum: Math.round(Number(t.localAmountBeforeVAT)),
            isProperty: t.isProperty,
            allocationNumber: t.allocationNumber ?? undefined,
        };
        transactions.push(transaction);
    }
    return transactions.sort((a, b) => a.invoiceDate.localeCompare(b.invoiceDate));
};
export async function getPcn874String(injector, businessId, rawMonthDate) {
    const monthDate = dateToTimelessDateString(startOfMonth(new Date(rawMonthDate)));
    const financialEntity = await injector
        .get(BusinessesProvider)
        .getBusinessByIdLoader.load(businessId);
    if (!financialEntity?.vat_number) {
        throw new Error(`Business entity ${businessId} has no VAT number`);
    }
    const vatRecords = await getVatRecords({ filters: { monthDate, financialEntityId: businessId } }, injector);
    const reportMonth = format(new Date(monthDate), 'yyyyMM');
    const reportContent = generatePcnFromVatRecords([
        ...vatRecords.income,
        ...vatRecords.expenses,
    ], financialEntity.vat_number, reportMonth);
    return { reportContent, monthDate, reportMonth, financialEntity };
}
const generatePcnFromVatRecords = (vatRecords, vatNumber, reportMonth) => {
    if (!yearMonthValidator(reportMonth)) {
        throw new Error(`Expected reportMonth to be legit date formed as YYYYMM, received "${reportMonth}"`);
    }
    if (!idValidator(vatNumber, 9)) {
        throw new Error(`Expected vatNumber to be 9 digits, received "${vatNumber}"`);
    }
    const transactions = transactionsFromVatReportRecords(vatRecords);
    const header = getHeaderDataFromRecords(transactions, vatNumber, reportMonth);
    const reportContent = pcnGenerator(header, transactions, { strict: false });
    return reportContent;
};
//# sourceMappingURL=pcn.helper.js.map