"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRandomInt = getRandomInt;
exports.formatDate = formatDate;
exports.getRandomAddress = getRandomAddress;
exports.generateCountry = generateCountry;
exports.generateString = generateString;
exports.generateText = generateText;
exports.generateFIO = generateFIO;
exports.generateEmail = generateEmail;
exports.generateMobilePhone = generateMobilePhone;
exports.generatePassword = generatePassword;
exports.chooseRandomBankAccount = chooseRandomBankAccount;
exports.chooseRandomOrganization = chooseRandomOrganization;
exports.generateDate = generateDate;
exports.generateDateBeforeToday = generateDateBeforeToday;
exports.generateDateInRange = generateDateInRange;
exports.pickRandom = pickRandom;
exports.parseDateFromDDMMYYYY = parseDateFromDDMMYYYY;
exports.generateINN = generateINN;
exports.generatePassportSeries = generatePassportSeries;
exports.generatePassportNumber = generatePassportNumber;
exports.generateSNILS = generateSNILS;
const form_data_constants_1 = require("./form-data-constants");
const adresses_1 = require("./data-to-generate/adresses");
const bank_accounts_1 = require("./data-to-generate/bank-accounts");
const countries_1 = require("./data-to-generate/countries");
/**
 * Утилита для генерации тестовых данных для заполнения полей форм
 */
// =========================
// Lazy loading для faker (ES Module)
// =========================
let fakerInstance = null;
/**
 * Загружает и возвращает экземпляр faker
 */
async function getFaker() {
    if (!fakerInstance) {
        const fakerModule = await Promise.resolve().then(() => __importStar(require('@faker-js/faker/locale/ru')));
        fakerInstance = fakerModule.faker;
    }
    return fakerInstance;
}
// =========================
// Вспомогательные функции
// =========================
/**
 * Получает случайное целое число в диапазоне [min, max]
 */
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
 * Получает случайный элемент из массива
 */
function getRandomElement(array) {
    return array[getRandomInt(0, array.length - 1)];
}
/**
 * Форматирует дату в формат dd.MM.yyyy
 */
function formatDate(date) {
    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const year = date.getFullYear();
    return `${day}.${month}.${year}`;
}
/**
 * Выбирает случайный адрес из списка объектов
 * @returns адрес
 * Adress - Адрес
 * AdressInRow - Вид адреса в строке грида
 */
function getRandomAddress() {
    const keys = Object.keys(adresses_1.addressBook);
    const randomKey = keys[Math.floor(Math.random() * keys.length)];
    return adresses_1.addressBook[randomKey];
}
/**
 * Генерирует случайную страну на русском языке
 * @returns случайная страна на русском языке
 */
async function generateCountry() {
    const countriesList = Object.keys(countries_1.countries);
    const randomCountry = getRandomElement(countriesList);
    const country = countries_1.countries[randomCountry];
    return {
        selectValue: country.selectValue,
        valueForSearch: country.valueForSearch
    };
}
async function generateString(type, length, characters) {
    const faker = await getFaker();
    switch (type) {
        case 'alphanumeric':
            if (!length || length <= 0) {
                throw new Error('Для генерации alphanumeric необходим положительный length');
            }
            return faker.string.alphanumeric(length);
        case 'alpha':
            if (!length || length <= 0) {
                throw new Error('Для генерации alpha необходим положительный length');
            }
            return faker.string.alpha(length);
        case 'numeric':
            if (!length || length <= 0) {
                throw new Error('Для генерации numeric необходим положительный length');
            }
            return faker.string.numeric(length);
        case 'symbol':
            return faker.string.symbol();
        case 'uuid':
            return faker.string.uuid();
        case 'fromCharacters':
            if (!characters) {
                throw new Error('Для генерации fromCharacters необходим параметр characters');
            }
            if (!length || length <= 0) {
                return faker.string.fromCharacters(characters);
            }
            return faker.string.fromCharacters(characters, length);
        case 'sample':
            return faker.string.sample();
        default:
            throw new Error(`Неизвестный тип генерации строки: ${type}`);
    }
}
/**
 * Генерирует текст разного типа (слова, предложения, абзацы)
 * @param type - тип текста
 * @param length - количество (например, предложений, слов, абзацей)
 * @returns слово, предложение, абзац
 */
async function generateText(type, length) {
    const faker = await getFaker();
    switch (type) {
        case 'word':
            return faker.lorem.word();
        case 'words':
            if (!length || length <= 0) {
                throw new Error('Для генерации words необходим положительный length');
            }
            return faker.lorem.words(length);
        case 'sentence':
            return faker.lorem.sentence();
        case 'sentences':
            if (!length || length <= 0) {
                throw new Error('Для генерации sentences необходим положительный length');
            }
            return faker.lorem.sentences(length);
        case 'paragraph':
            return faker.lorem.paragraph();
        case 'paragraphs':
            if (!length || length <= 0) {
                throw new Error('Для генерации paragraphs необходим положительный length');
            }
            return faker.lorem.paragraphs(length);
        case 'buzzPhrase':
            return faker.company.buzzPhrase();
        default:
            throw new Error(`Неизвестный тип генерации: ${type}`);
    }
}
/**
 * Генерирует случайное ФИО
 * @returns объект с случайным ФИО
 * lastName - случайная фамилия
 * firstName - случайное имя
 * middleName - случайное имя
 */
async function generateFIO() {
    const faker = await getFaker();
    const gender = Math.random() > 0.5 ? 'male' : 'female';
    const lastName = faker.person.lastName(gender); // Случайная фамилия
    const firstName = faker.person.firstName(gender); // Случайное имя
    const middleName = faker.person.middleName(gender); // Случайное отчество
    return { lastName, firstName, middleName };
}
/**
 * Генерирует случайный email
 * @returns случайный email
 */
async function generateEmail() {
    const faker = await getFaker();
    return faker.internet.email();
}
/**
 * Генерирует случайный мобильный телефон с возможностью выбора формата
 * @param format - формат номера: 'default' (как faker, с () и пробелами), 'withSpaces' (без (), с пробелами), 'noSpaces' (без () и пробелов)
 * @returns случайный мобильный телефон в указанном формате
 *
 * @example
 * generateMobilePhone(); // "(912) 345-67-89" (формат по умолчанию)
 * generateMobilePhone('default'); // "(912) 345-67-89"
 * generateMobilePhone('withSpaces'); // "912 345-67-89"
 * generateMobilePhone('noSpaces'); // "9123456789"
 */
async function generateMobilePhone(format = 'default') {
    const faker = await getFaker();
    const phone = faker.phone.number();
    if (format === 'default') {
        return phone;
    }
    if (format === 'withSpaces') {
        // Убираем скобки, оставляем пробелы и дефисы
        return phone.replace(/[()]/g, '');
    }
    if (format === 'noSpaces') {
        // Убираем все нецифровые символы
        return phone.replace(/\D/g, '');
    }
    return phone;
}
async function generatePassword() {
    const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/!@#$^&*()-+';
    let password;
    do {
        password = await generateString('fromCharacters', getRandomInt(8, 20), characters);
    } while (!/(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])/.test(password));
    return password;
}
/**
 * Выбирает случайный банковский счет и наименование банка
 * @returns случайный банковский счет и наименование банка
 */
function chooseRandomBankAccount() {
    const accounts = Object.keys(bank_accounts_1.bank_accounts);
    const account = getRandomElement(accounts);
    const bank = bank_accounts_1.bank_accounts[account];
    return { account, bank };
}
/**
 * Выбирает случайную организацию из списка
 * @param organizations - объект с организациями
 * @returns случайная организация
 */
function chooseRandomOrganization(organizations) {
    const organizationsList = Object.keys(organizations);
    const randomOrganization = getRandomElement(organizationsList);
    return organizations[randomOrganization];
}
// =========================
// Функции генерации текста
// =========================
// =========================
// Функции генерации дат
// =========================
/**
 * Генерирует случайную дату в заданном диапазоне
 *
 * @param options - опции генерации даты
 * @returns отформатированная дата в формате dd.MM.yyyy
 *
 * @example
 * generateDate(); // случайная дата от 01.01.1920 до сегодня
 * generateDate({ minDate: new Date(2000, 0, 1), maxDate: new Date(2020, 11, 31) });
 * generateDate({ maxDate: 'today' }); // дата не выше текущей
 * generateDate({ minDate: 'today' }); // дата не ниже текущей (только сегодня)
 * generateDate({ minDate: 'today', maxDate: 'today' }); // всегда сегодняшняя дата
 */
function generateDate(options) {
    const { minDate = form_data_constants_1.DEFAULT_MIN_DATE, maxDate = 'today', } = options || {};
    // Определяем минимальную дату
    const min = minDate === 'today' ? new Date() : minDate;
    // Определяем максимальную дату
    const max = maxDate === 'today' ? new Date() : maxDate;
    // Проверяем корректность диапазона
    if (min > max) {
        throw new Error('Минимальная дата не может быть больше максимальной');
    }
    // Генерируем случайную дату в диапазоне
    const minTime = min.getTime();
    const maxTime = max.getTime();
    const randomTime = getRandomInt(minTime, maxTime);
    const randomDate = new Date(randomTime);
    return formatDate(randomDate);
}
/**
 * Генерирует случайную дату не выше текущей даты
 *
 * @param minDate - минимальная дата (по умолчанию 01.01.1920)
 * @returns отформатированная дата в формате dd.MM.yyyy
 *
 * @example
 * generateDateBeforeToday(); // дата от 01.01.1920 до сегодня
 * generateDateBeforeToday(new Date(2000, 0, 1)); // дата от 01.01.2000 до сегодня
 */
function generateDateBeforeToday(minDate) {
    return generateDate({ minDate, maxDate: 'today' });
}
/**
 * Генерирует случайную дату в указанном диапазоне
 *
 * @param minDate - минимальная дата
 * @param maxDate - максимальная дата
 * @returns отформатированная дата в формате dd.MM.yyyy
 *
 * @example
 * generateDateInRange(new Date(2000, 0, 1), new Date(2020, 11, 31));
 */
function generateDateInRange(minDate, maxDate) {
    return generateDate({ minDate, maxDate });
}
// =========================
// Функции выбора из массивов
// =========================
/**
 * Выбирает случайный элемент из массива
 *
 * @param array - массив элементов
 * @returns случайный элемент массива
 * @throws Error если массив пустой
 *
 * @example
 * const activities = ["Горнорудные работы", "Строительство", "Производство"];
 * const random = pickRandom(activities); // один из элементов массива
 */
function pickRandom(array) {
    if (!array || array.length === 0) {
        throw new Error('Массив не может быть пустым');
    }
    return getRandomElement(array);
}
function parseDateFromDDMMYYYY(dateStr) {
    const [day, month, year] = dateStr.split('.').map(Number);
    return new Date(year, month - 1, day);
}
/**
 * Генерирует случайный ИНН
 *
 * @param type - тип ИНН: 'individual' (12 цифр для физ. лица/ИП) или 'legal' (10 цифр для юр. лица)
 * @returns валидный ИНН с корректной контрольной суммой
 *
 * @example
 * generateINN(); // случайный 12-значный ИНН
 * generateINN('individual'); // 12-значный ИНН
 * generateINN('legal'); // 10-значный ИНН
 */
function generateINN(type = 'individual') {
    if (type === 'legal') {
        // ИНН юридического лица - 10 цифр
        // Генерируем первые 9 цифр случайно
        const digits = [];
        for (let i = 0; i < 9; i++) {
            digits.push(getRandomInt(0, 9));
        }
        // Вычисляем контрольную сумму для 10-значного ИНН
        // Коэффициенты: [2, 4, 10, 3, 5, 9, 4, 6, 8]
        const coefficients = [2, 4, 10, 3, 5, 9, 4, 6, 8];
        let sum = 0;
        for (let i = 0; i < 9; i++) {
            sum += digits[i] * coefficients[i];
        }
        const checksum = sum % 11;
        const controlDigit = checksum < 10 ? checksum : 0;
        digits.push(controlDigit);
        return digits.join('');
    }
    else {
        // ИНН физического лица/ИП - 12 цифр
        // Генерируем первые 10 цифр случайно
        const digits = [];
        for (let i = 0; i < 10; i++) {
            digits.push(getRandomInt(0, 9));
        }
        // Вычисляем первую контрольную сумму (11-я цифра)
        // Коэффициенты: [7, 2, 4, 10, 3, 5, 9, 4, 6, 8]
        const coefficients1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8];
        let sum1 = 0;
        for (let i = 0; i < 10; i++) {
            sum1 += digits[i] * coefficients1[i];
        }
        const checksum1 = sum1 % 11;
        const controlDigit1 = checksum1 < 10 ? checksum1 : 0;
        digits.push(controlDigit1);
        // Вычисляем вторую контрольную сумму (12-я цифра)
        // Коэффициенты: [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8]
        const coefficients2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8];
        let sum2 = 0;
        for (let i = 0; i < 11; i++) {
            sum2 += digits[i] * coefficients2[i];
        }
        const checksum2 = sum2 % 11;
        const controlDigit2 = checksum2 < 10 ? checksum2 : 0;
        digits.push(controlDigit2);
        return digits.join('');
    }
}
/**
 * Генерирует серию паспорта (4 цифры)
 * @returns серия паспорта в формате XXXX
 */
async function generatePassportSeries() {
    return await generateString('numeric', 4);
}
/**
 * Генерирует номер паспорта (6 цифр)
 * @returns номер паспорта в формате XXXXXX
 */
async function generatePassportNumber() {
    return await generateString('numeric', 6);
}
/**
 * Генерирует случайный СНИЛС
 *
 * @param formatted - форматировать ли результат (XXX-XXX-XXX YY) или вернуть без форматирования (XXXXXXXXXYY)
 * @returns валидный СНИЛС с корректной контрольной суммой
 *
 * @example
 * generateSNILS(); // "123-456-789 01"
 * generateSNILS(false); // "12345678901"
 */
function generateSNILS(formatted = true) {
    // Генерируем первые 9 цифр случайно
    // Важно: не должно быть всех одинаковых цифр (например, 000-000-000)
    const digits = [];
    for (let i = 0; i < 9; i++) {
        digits.push(getRandomInt(0, 9));
    }
    // Проверяем, что не все цифры одинаковые
    const allSame = digits.every(d => d === digits[0]);
    if (allSame) {
        // Если все одинаковые, меняем последнюю цифру
        digits[8] = (digits[8] + 1) % 10;
    }
    // Вычисляем контрольное число
    let sum = 0;
    for (let i = 0; i < 9; i++) {
        sum += digits[i] * (9 - i);
    }
    let controlNumber = sum % 101;
    // Если контрольное число равно 100 или 101, заменяем на 00
    if (controlNumber === 100 || controlNumber === 101) {
        controlNumber = 0;
    }
    // Форматируем контрольное число (две цифры)
    const controlStr = String(controlNumber).padStart(2, '0');
    if (formatted) {
        // Формат: XXX-XXX-XXX YY
        const part1 = digits.slice(0, 3).join('');
        const part2 = digits.slice(3, 6).join('');
        const part3 = digits.slice(6, 9).join('');
        return `${part1}-${part2}-${part3} ${controlStr}`;
    }
    else {
        // Формат: XXXXXXXXXYY
        return digits.join('') + controlStr;
    }
}
