import { z } from 'zod';
import { ALLOWED_TAX_ADJUSTMENT_CODES, NEGATIVE_ALLOWED_TAX_ADJUSTMENTS_CODES, TAX_ADJUSTMENT_CODE_NAMES, } from '../types/index.js';
/**
 * Tax Adjustment Record Schema
 * Based on the SHAAM 6111 specification (IncomeTax_software-houses-6111-2023.pdf)
 */
// Create a set for faster lookup of allowed codes
export const allowedCodesSet = new Set(ALLOWED_TAX_ADJUSTMENT_CODES);
export const negativeAllowedCodesSet = new Set(NEGATIVE_ALLOWED_TAX_ADJUSTMENTS_CODES);
function codeToName(code) {
    return `${TAX_ADJUSTMENT_CODE_NAMES[code] ?? 'Unknown code'} (${code})`;
}
// Create the Tax Adjustment record schema
const taxAdjustmentRecordSchema = z
    .object({
    // קוד שדה - Field code
    code: z
        .number()
        .int()
        .refine(code => allowedCodesSet.has(code), {
        message: 'Invalid code for tax adjustment section',
    }),
    // סכום - Amount
    amount: z.number().int(),
})
    .superRefine((record, ctx) => {
    // Validate that non-negative codes don't have negative amounts
    if (!negativeAllowedCodesSet.has(record.code) && record.amount < 0) {
        ctx.addIssue({
            code: z.ZodIssueCode.custom,
            message: `Code ${codeToName(record.code)} does not allow negative amounts`,
            path: ['amount'],
        });
    }
});
// Define the validation logic for each summary code
const summaryValidations = {
    //   100:
    //   103:
    //   104: validated on the report level
    370: {
        formula: (map) => {
            return ([110, 120, 140, 150, 160, 181, 182, 183, 184, 190, 310, 330, 350, 360]
                .map(code => map.get(code) || 0)
                .reduce((a, b) => a + b, 0) -
                [130, 135, 170, 180, 200, 300, 320]
                    .map(code => map.get(code) || 0)
                    .reduce((a, b) => a + b, 0));
        },
        description: '110+120-130-135+140+150+160-170-180+181+182+183+184+190-200-300+310-320+330+350+360',
    },
    //   383:
    //   400: validated on the report level
    500: {
        formula: (map) => {
            return (map.get(400) || 0) - (map.get(430) || 0) - (map.get(480) || 0) + (map.get(490) || 0);
        },
        description: '400-430-480+490',
    },
    //   600:
};
// Schema for an array of Tax Adjustment records
export const taxAdjustmentArraySchema = z
    .array(taxAdjustmentRecordSchema)
    .max(150)
    .superRefine((records, ctx) => {
    // Check for unique code values & create a map for faster lookups
    const codeToAmountMap = checkForUniqueCodes(records, ctx);
    // Validate each summary field with its formula
    for (const [codeStr, validation] of Object.entries(summaryValidations)) {
        const code = parseInt(codeStr);
        if (codeToAmountMap.has(code)) {
            const actualAmount = codeToAmountMap.get(code);
            const expectedAmount = validation.formula(codeToAmountMap);
            if (actualAmount !== expectedAmount) {
                const index = records.findIndex(r => r.code === code);
                ctx.addIssue({
                    code: z.ZodIssueCode.custom,
                    message: `Value for code ${codeToName(code)} should equal the sum: ${validation.description}`,
                    path: [index, 'amount'],
                });
            }
        }
    }
});
function checkForUniqueCodes(records, ctx) {
    const codeMap = new Map();
    records.map((record, index) => {
        if (codeMap.has(record.code)) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: `Duplicate code ${codeToName(record.code)} found`,
                path: [index, 'code'],
            });
        }
        codeMap.set(record.code, record.amount);
    });
    return codeMap;
}
//# sourceMappingURL=tax-adjustment.js.map