import { balanceSheetArraySchema, headerSchema, profitLossArraySchema, taxAdjustmentArraySchema, } from '../schemas/index.js';
import { IndividualOrCompanyEnum, } from '../types/index.js';
import { code104Description, code400Description, validateCode104, validateCode400, } from './specific-code-validations.js';
/**
 * Validates a ReportData object using Zod schemas.
 * @param data The ReportData object to validate.
 * @returns A ValidationResult object containing validation status and errors.
 */
export function validateData(data) {
    const errors = [];
    // Validate header
    if (data.header) {
        const headerValidation = headerSchema.safeParse(data.header);
        if (!headerValidation.success) {
            for (const issue of headerValidation.error.issues) {
                errors.push({
                    path: `header.${issue.path.join('.')}`,
                    message: issue.message,
                    code: issue.code,
                    value: issue.input,
                });
            }
        }
    }
    else {
        errors.push({
            path: 'header',
            message: 'Header is required',
        });
    }
    // Validate profit and loss
    if (Array.isArray(data.profitAndLoss)) {
        const profitLossValidation = profitLossArraySchema.safeParse(data.profitAndLoss);
        if (!profitLossValidation.success) {
            for (const issue of profitLossValidation.error.issues) {
                errors.push({
                    path: ['profitAndLoss', ...issue.path].join('.'),
                    message: issue.message,
                    code: issue.code,
                    value: issue.input,
                });
            }
        }
    }
    // Validate tax adjustment
    if (Array.isArray(data.taxAdjustment)) {
        const taxAdjustmentValidation = taxAdjustmentArraySchema.safeParse(data.taxAdjustment);
        if (!taxAdjustmentValidation.success) {
            for (const issue of taxAdjustmentValidation.error.issues) {
                errors.push({
                    path: ['taxAdjustment', ...issue.path].join('.'),
                    message: issue.message,
                    code: issue.code,
                    value: issue.input,
                });
            }
        }
    }
    const hasBalanceSheet = Array.isArray(data.balanceSheet) && data.balanceSheet.length > 0;
    // Validate balance sheet only when present
    if (hasBalanceSheet) {
        const balanceSheetValidation = balanceSheetArraySchema.safeParse(data.balanceSheet);
        if (!balanceSheetValidation.success) {
            for (const issue of balanceSheetValidation.error.issues) {
                errors.push({
                    path: ['balanceSheet', ...issue.path].join('.'),
                    message: issue.message,
                    code: issue.code,
                    value: issue.input,
                });
            }
        }
    }
    // Determine whether a balance sheet **must** be present
    const mustHaveBalanceSheet = data.individualOrCompany === IndividualOrCompanyEnum.COMPANY;
    // Enforce presence for companies
    if (mustHaveBalanceSheet && !hasBalanceSheet) {
        errors.push({
            path: 'balanceSheet',
            message: 'Balance sheet is required for companies',
        });
    }
    if (data.header.profitLossEntryCount !== data.profitAndLoss.length) {
        errors.push({
            path: 'header.profitLossEntryCount',
            message: 'Profit and Loss entry count does not match the number of records',
        });
    }
    if (data.header.taxAdjustmentEntryCount !== data.taxAdjustment.length) {
        errors.push({
            path: 'header.taxAdjustmentEntryCount',
            message: 'Tax Adjustment entry count does not match the number of records',
        });
    }
    if (data.header.balanceSheetEntryCount !== (data.balanceSheet?.length ?? 0)) {
        errors.push({
            path: 'header.balanceSheetEntryCount',
            message: 'Balance Sheet entry count does not match the number of records',
        });
    }
    // validate rule 3.7 profitAndLoss code 6666 equals to taxAdjustment code 100
    const code6666Entry = data.profitAndLoss.find(item => item.code === 6666);
    const code100Entry = data.taxAdjustment.find(item => item.code === 100);
    if (code6666Entry && code100Entry && code6666Entry.amount !== code100Entry.amount) {
        errors.push({
            path: 'custom',
            message: 'Profit and Loss code 6666 must equal Tax Adjustment code 100',
        });
    }
    else if (!code6666Entry || !code100Entry) {
        errors.push({
            path: 'custom',
            message: 'Both Profit and Loss code 6666 and Tax Adjustment code 100 must be present and equal',
        });
    }
    const validationAmounts = {
        100: 0,
        103: 0,
        104: 0,
        370: 0,
        383: 0,
        400: 0,
    };
    data.taxAdjustment.map(record => {
        if (record.code in validationAmounts) {
            validationAmounts[record.code] = record.amount;
        }
    });
    const ifrsReportingOption = data.header.ifrsReportingOption;
    // validate code 104 according to rule 2.6
    if (!validateCode104(validationAmounts, ifrsReportingOption)) {
        errors.push({
            path: 'custom',
            message: code104Description(ifrsReportingOption),
        });
    }
    // validate code 400 according to rule 2.7
    if (!validateCode400(validationAmounts, ifrsReportingOption)) {
        errors.push({
            path: 'custom',
            message: code400Description(ifrsReportingOption),
        });
    }
    // validate rule 3.8 profitAndLoss sum of codes 1450 & 2095 equals to balanceSheet code 7800
    const code1450Amount = data.profitAndLoss.find(item => item.code === 1450)?.amount;
    const code2095Amount = data.profitAndLoss.find(item => item.code === 2095)?.amount;
    const balanceSheet7800Amount = data.balanceSheet?.find(item => item.code === 7800)?.amount;
    if ((code1450Amount !== undefined ||
        code2095Amount !== undefined ||
        balanceSheet7800Amount !== undefined) &&
        (code1450Amount ?? 0) + (code2095Amount ?? 0) !== balanceSheet7800Amount) {
        errors.push({
            path: 'custom',
            message: 'Sum of Profit and Loss codes 1450 and 2095 must equal Balance Sheet code 7800',
        });
    }
    return {
        isValid: errors.length === 0,
        errors,
    };
}
//# sourceMappingURL=validate-data.js.map