import { z } from 'zod';
import { CRLF } from '../../format/index.js';
import { DocumentTypeEnum } from '../../types/index.js';
import { formatField, formatNumericField } from '../index.js';
/**
 * D120 - Payment/receipt record
 * Fields 1300-1324 based on SHAAM 1.31 specification
 */
export const D120Schema = z.object({
    // Field 1300: Record code (4) - Required - Alphanumeric - Value: D120
    code: z.literal('D120').describe('Record type code - always "D120"'),
    // Field 1301: Record number in file (9) - Required - Numeric
    recordNumber: z
        .string()
        .min(1)
        .max(9)
        .regex(/^\d+$/)
        .describe('Sequential record number in file'),
    // Field 1302: Tax ID (9) - Required - Numeric
    vatId: z.string().min(1).max(9).regex(/^\d+$/).describe('VAT identification number'),
    // Field 1303: Document type (3) - Required - Numeric
    documentType: DocumentTypeEnum.describe('Document type - see Appendix 1, Note 1'),
    // Field 1304: Document number (20) - Required - Alphanumeric
    documentNumber: z.string().min(1).max(20).describe('Document number'),
    // Field 1305: Line number in document (4) - Required - Numeric
    lineNumber: z.string().min(1).max(4).regex(/^\d+$/).describe('Line number in document'),
    // Field 1306: Payment method (1) - Required - Numeric
    paymentMethod: z
        .string()
        .min(1)
        .max(1)
        .regex(/^[1-9]$/)
        .describe('Payment method type: 1-Cash, 2-Check, 3-Credit card, 4-Bank transfer, 5-Voucher, 6-Exchange slip, 7-Promissory note, 8-Standing order, 9-Other'),
    // Field 1307: Bank number (10) - Conditional - Numeric - Check only
    bankNumber: z.string().max(10).regex(/^\d*$/).default('').describe('Bank number - check only'),
    // Field 1308: Branch number (10) - Conditional - Numeric - Check only
    branchNumber: z
        .string()
        .max(10)
        .regex(/^\d*$/)
        .default('')
        .describe('Branch number - check only'),
    // Field 1309: Account number (15) - Conditional - Numeric - Check only
    accountNumber: z
        .string()
        .max(15)
        .regex(/^\d*$/)
        .default('')
        .describe('Account number - check only'),
    // Field 1310: Check number (10) - Conditional - Numeric - Check only
    checkNumber: z.string().max(10).regex(/^\d*$/).default('').describe('Check number - check only'),
    // Field 1311: Payment due date (8) - Optional - Numeric - Format YYYYMMDD
    paymentDueDate: z
        .string()
        .max(8)
        .regex(/^(\d{8}|)$/)
        .default('')
        .describe('Payment due date YYYYMMDD - check or credit card only'),
    // Field 1312: Line amount (15) - Required - Alphanumeric - Format X9(12)V99
    lineAmount: z
        .string()
        .min(1)
        .max(15)
        .regex(/^(\d{1,13}(\.\d{2})?|)$/)
        .describe('Line amount'),
    // Field 1313: Acquirer code (1) - Optional - Numeric
    acquirerCode: z
        .string()
        .max(1)
        .regex(/^[1-6]?$/)
        .default('')
        .describe('Acquirer code: 1-Isracard, 2-Cal, 3-Diners, 4-Amex, 6-Leumi Card'),
    // Field 1314: Card brand (20) - Optional - Alphanumeric
    cardBrand: z.string().max(20).default('').describe('Card brand name'),
    // Field 1315: Credit transaction type (1) - Optional - Numeric
    creditTransactionType: z
        .string()
        .max(1)
        .regex(/^[1-5]?$/)
        .default('')
        .describe('Credit transaction type: 1-Regular, 2-Installments, 3-Credit, 4-Deferred, 5-Other'),
    // Field 1316: First payment amount (0) - Deprecated - Alphanumeric
    firstPaymentAmount: z.string().max(0).default('').describe('First payment amount (deprecated)'),
    // Field 1317: Installments count (0) - Deprecated - Alphanumeric
    installmentsCount: z.string().max(0).default('').describe('Installments count (deprecated)'),
    // Field 1318: Additional payment amount (0) - Deprecated - Alphanumeric
    additionalPaymentAmount: z
        .string()
        .max(0)
        .default('')
        .describe('Additional payment amount (deprecated)'),
    // Field 1319: Reserved field (0) - Deprecated - Alphanumeric
    reserved1: z.string().max(0).default('').describe('Reserved field 1 (deprecated)'),
    // Field 1320: Branch ID (7) - Required - Alphanumeric - Required if field 1034 = 1
    branchId: z
        .string()
        .max(7)
        .default('')
        .describe('Branch/sector ID - required if field 1034 = 1, see Note 3'),
    // Field 1321: Reserved field (0) - Deprecated - Alphanumeric
    reserved2: z.string().max(0).default('').describe('Reserved field 2 (deprecated)'),
    // Field 1322: Document date (8) - Required - Numeric - Format YYYYMMDD
    documentDate: z
        .string()
        .min(1)
        .max(8)
        .regex(/^\d{8}$/)
        .describe('Document date YYYYMMDD - see Note 12'),
    // Field 1323: Header link field (7) - Optional - Numeric - For linking to C100
    headerLinkField: z
        .string()
        .max(7)
        .regex(/^\d*$/)
        .default('')
        .describe('Header connecting field - for linking to C100, see Note 11'),
    // Field 1324: Reserved field (60) - Optional - Alphanumeric
    reserved: z.string().max(60).default('').describe('Reserved field for future use'),
});
/**
 * Encodes a D120 record to fixed-width string format
 * Total line width: 222 characters + CRLF (4+9+9+3+20+4+1+10+10+15+10+8+15+1+20+1+0+0+0+0+7+0+8+7+60)
 */
export function encodeD120(input) {
    const fields = [
        formatField(input.code, 4, 'left'), // Field 1300: Record code (4) - Alphanumeric
        formatNumericField(input.recordNumber, 9), // Field 1301: Record number (9) - Numeric, zero-padded
        formatNumericField(input.vatId, 9), // Field 1302: VAT ID (9) - Numeric, zero-padded
        formatNumericField(input.documentType, 3), // Field 1303: Document type (3) - Numeric, zero-padded
        formatField(input.documentNumber, 20, 'left'), // Field 1304: Document number (20) - Alphanumeric
        formatNumericField(input.lineNumber, 4), // Field 1305: Line number (4) - Numeric, zero-padded
        formatNumericField(input.paymentMethod, 1), // Field 1306: Payment method (1) - Numeric, zero-padded
        formatField(input.bankNumber, 10, 'left'), // Field 1307: Bank number (10) - Conditional, space-padded when empty
        formatField(input.branchNumber, 10, 'left'), // Field 1308: Branch number (10) - Conditional, space-padded when empty
        formatField(input.accountNumber, 15, 'left'), // Field 1309: Account number (15) - Conditional, space-padded when empty
        formatField(input.checkNumber, 10, 'left'), // Field 1310: Check number (10) - Conditional, space-padded when empty
        formatField(input.paymentDueDate, 8, 'left'), // Field 1311: Payment due date (8) - Optional date field, space-padded when empty
        formatField(input.lineAmount, 15, 'left'), // Field 1312: Line amount (15) - Alphanumeric monetary format
        formatField(input.acquirerCode, 1, 'left'), // Field 1313: Acquirer code (1) - Optional, space-padded when empty
        formatField(input.cardBrand, 20, 'left'), // Field 1314: Card brand (20) - Alphanumeric
        formatField(input.creditTransactionType, 1, 'left'), // Field 1315: Credit transaction type (1) - Optional, space-padded when empty
        formatField(input.firstPaymentAmount, 0, 'left'), // Field 1316: First payment amount (0) - Deprecated
        formatField(input.installmentsCount, 0, 'left'), // Field 1317: Installments count (0) - Deprecated
        formatField(input.additionalPaymentAmount, 0, 'left'), // Field 1318: Additional payment amount (0) - Deprecated
        formatField(input.reserved1, 0, 'left'), // Field 1319: Reserved 1 (0) - Deprecated
        formatField(input.branchId, 7, 'left'), // Field 1320: Branch ID (7) - Alphanumeric
        formatField(input.reserved2, 0, 'left'), // Field 1321: Reserved 2 (0) - Deprecated
        formatNumericField(input.documentDate, 8), // Field 1322: Document date (8) - Numeric, zero-padded
        formatField(input.headerLinkField, 7, 'left'), // Field 1323: Header link field (7) - Optional, space-padded when empty
        formatField(input.reserved, 60, 'left'), // Field 1324: Reserved (60) - Alphanumeric
    ];
    return fields.join('') + CRLF;
}
/**
 * Parses a fixed-width D120 record line back to object
 * Expected line length: 222 characters (excluding CRLF)
 */
export function parseD120(line) {
    // Remove CRLF if present
    const cleanLine = line.replace(/\r?\n$/, '');
    if (cleanLine.length !== 222) {
        throw new Error(`Invalid D120 record length: expected 222 characters, got ${cleanLine.length}`);
    }
    // Extract fields at their fixed positions
    let pos = 0;
    const code = cleanLine.slice(pos, pos + 4).trim();
    pos += 4;
    const recordNumber = cleanLine
        .slice(pos, pos + 9)
        .trim()
        .replace(/^0+/, '') || '0'; // Strip leading zeros
    pos += 9;
    const vatId = cleanLine
        .slice(pos, pos + 9)
        .trim()
        .replace(/^0+/, '') || '0'; // Strip leading zeros
    pos += 9;
    const documentType = (cleanLine
        .slice(pos, pos + 3)
        .trim()
        .replace(/^0+/, '') || '0'); // Strip leading zeros
    pos += 3;
    const documentNumber = cleanLine.slice(pos, pos + 20).trim();
    pos += 20;
    const lineNumber = cleanLine
        .slice(pos, pos + 4)
        .trim()
        .replace(/^0+/, '') || '0'; // Strip leading zeros
    pos += 4;
    const paymentMethod = cleanLine
        .slice(pos, pos + 1)
        .trim()
        .replace(/^0+/, '') || '0'; // Strip leading zeros
    pos += 1;
    const bankNumber = cleanLine.slice(pos, pos + 10).trim();
    const bankNumberProcessed = bankNumber === '' ? '' : bankNumber.replace(/^0+/, '') || '0'; // Strip leading zeros only if not empty
    pos += 10;
    const branchNumber = cleanLine.slice(pos, pos + 10).trim();
    const branchNumberProcessed = branchNumber === '' ? '' : branchNumber.replace(/^0+/, '') || '0'; // Strip leading zeros only if not empty
    pos += 10;
    const accountNumber = cleanLine.slice(pos, pos + 15).trim();
    const accountNumberProcessed = accountNumber === '' ? '' : accountNumber.replace(/^0+/, '') || '0'; // Strip leading zeros only if not empty
    pos += 15;
    const checkNumber = cleanLine.slice(pos, pos + 10).trim();
    const checkNumberProcessed = checkNumber === '' ? '' : checkNumber.replace(/^0+/, '') || '0'; // Strip leading zeros only if not empty
    pos += 10;
    const paymentDueDate = cleanLine.slice(pos, pos + 8).trim();
    const paymentDueDateProcessed = paymentDueDate; // Keep as-is since it's a date field or empty
    pos += 8;
    const lineAmount = cleanLine.slice(pos, pos + 15).trim(); // Alphanumeric monetary format
    pos += 15;
    const acquirerCode = cleanLine.slice(pos, pos + 1).trim();
    const acquirerCodeProcessed = acquirerCode; // Keep as-is since it's a single digit field or empty
    pos += 1;
    const cardBrand = cleanLine.slice(pos, pos + 20).trim();
    pos += 20;
    const creditTransactionType = cleanLine.slice(pos, pos + 1).trim();
    const creditTransactionTypeProcessed = creditTransactionType; // Keep as-is since it's a single digit field or empty
    pos += 1;
    const firstPaymentAmount = cleanLine.slice(pos, pos + 0).trim();
    pos += 0; // 0 width
    const installmentsCount = cleanLine.slice(pos, pos + 0).trim();
    pos += 0; // 0 width
    const additionalPaymentAmount = cleanLine.slice(pos, pos + 0).trim();
    pos += 0; // 0 width
    const reserved1 = cleanLine.slice(pos, pos + 0).trim();
    pos += 0; // 0 width
    const branchId = cleanLine.slice(pos, pos + 7).trim();
    pos += 7;
    const reserved2 = cleanLine.slice(pos, pos + 0).trim();
    pos += 0; // 0 width
    const documentDate = cleanLine
        .slice(pos, pos + 8)
        .trim()
        .replace(/^0+/, '') || '0'; // Strip leading zeros
    pos += 8;
    const headerLinkField = cleanLine.slice(pos, pos + 7).trim();
    const headerLinkFieldProcessed = headerLinkField === '' ? '' : headerLinkField.replace(/^0+/, '') || '0'; // Strip leading zeros only if not empty
    pos += 7;
    const reserved = cleanLine.slice(pos, pos + 60).trim();
    // Validate the code field
    if (code !== 'D120') {
        throw new Error(`Invalid D120 record code: expected "D120", got "${code}"`);
    }
    const parsed = {
        code,
        recordNumber,
        vatId,
        documentType,
        documentNumber,
        lineNumber,
        paymentMethod,
        bankNumber: bankNumberProcessed,
        branchNumber: branchNumberProcessed,
        accountNumber: accountNumberProcessed,
        checkNumber: checkNumberProcessed,
        paymentDueDate: paymentDueDateProcessed,
        lineAmount,
        acquirerCode: acquirerCodeProcessed,
        cardBrand,
        creditTransactionType: creditTransactionTypeProcessed,
        firstPaymentAmount,
        installmentsCount,
        additionalPaymentAmount,
        reserved1,
        branchId,
        reserved2,
        documentDate,
        headerLinkField: headerLinkFieldProcessed,
        reserved,
    };
    // Validate against schema
    return D120Schema.parse(parsed);
}
//# sourceMappingURL=d120.js.map