"use strict";
/**
 * @fileoverview Step functions for CLI actions.
 * Each step is an independent, reusable function that performs a specific task.
 * Steps return any data needed by subsequent steps or the calling action.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.stepCreateDirectoryStructure = stepCreateDirectoryStructure;
exports.stepCopyTemplateFiles = stepCopyTemplateFiles;
exports.stepDownloadTestlib = stepDownloadTestlib;
exports.stepSaveTestlibToDirectory = stepSaveTestlibToDirectory;
exports.stepValidateConfigForValidator = stepValidateConfigForValidator;
exports.stepCompileValidator = stepCompileValidator;
exports.stepValidateAllTestsets = stepValidateAllTestsets;
exports.stepValidateSingleTest = stepValidateSingleTest;
exports.stepValidateGroup = stepValidateGroup;
exports.stepValidateTestset = stepValidateTestset;
exports.stepValidateConfigForGeneration = stepValidateConfigForGeneration;
exports.stepCompileGeneratorsForTestsets = stepCompileGeneratorsForTestsets;
exports.stepGenerateAllTestsets = stepGenerateAllTestsets;
exports.stepCompileGeneratorsForSingleTest = stepCompileGeneratorsForSingleTest;
exports.stepGenerateSingleTest = stepGenerateSingleTest;
exports.stepCompileGeneratorsForGroup = stepCompileGeneratorsForGroup;
exports.stepGenerateTestsForGroup = stepGenerateTestsForGroup;
exports.stepCompileGeneratorsForTestset = stepCompileGeneratorsForTestset;
exports.stepGenerateTestsForTestset = stepGenerateTestsForTestset;
exports.stepValidateConfigForSolutions = stepValidateConfigForSolutions;
exports.stepCompileSolutions = stepCompileSolutions;
exports.stepRunSolutionsOnAllTestsets = stepRunSolutionsOnAllTestsets;
exports.stepRunSolutionsOnTestset = stepRunSolutionsOnTestset;
exports.stepRunSolutionsOnTest = stepRunSolutionsOnTest;
exports.stepRunSolutionsOnGroup = stepRunSolutionsOnGroup;
exports.stepCompileChecker = stepCompileChecker;
exports.stepValidateConfigForChecker = stepValidateConfigForChecker;
exports.stepTestChecker = stepTestChecker;
exports.stepValidateConfigForSolutionTest = stepValidateConfigForSolutionTest;
exports.stepTestSolutionBehavior = stepTestSolutionBehavior;
exports.stepGenerateTestsForVerification = stepGenerateTestsForVerification;
exports.stepTestValidator = stepTestValidator;
exports.stepValidateGeneratedTests = stepValidateGeneratedTests;
exports.stepCompileSolutionsForVerification = stepCompileSolutionsForVerification;
exports.stepRunSolutionsForVerification = stepRunSolutionsForVerification;
exports.stepVerifySolutionsAgainstMainCorrect = stepVerifySolutionsAgainstMainCorrect;
const formatter_1 = require("./formatter");
const validator_1 = require("./helpers/validator");
const checker_1 = require("./helpers/checker");
const generator_1 = require("./helpers/generator");
const testset_1 = require("./helpers/testset");
const solution_1 = require("./helpers/solution");
const create_template_1 = require("./helpers/create-template");
const testlib_download_1 = require("./helpers/testlib-download");
const utils_1 = require("./helpers/utils");
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
// ============================================================================
// CREATE TEMPLATE STEPS
// ============================================================================
function stepCreateDirectoryStructure(stepNum, directory) {
    formatter_1.fmt.step(stepNum, 'Creating Directory Structure');
    const problemDir = path_1.default.resolve(process.cwd(), directory);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Target directory: ${formatter_1.fmt.highlight(directory)}`);
    fs_1.default.mkdirSync(problemDir, { recursive: true });
    formatter_1.fmt.stepComplete('Directory created');
}
function stepCopyTemplateFiles(stepNum, directory) {
    formatter_1.fmt.step(stepNum, 'Copying Template Files');
    (0, create_template_1.copyTemplate)(path_1.default.resolve(__dirname, '../template'), path_1.default.resolve(process.cwd(), directory));
    formatter_1.fmt.stepComplete('Template files copied');
}
// ============================================================================
// DOWNLOAD TESTLIB STEPS
// ============================================================================
async function stepDownloadTestlib(stepNum) {
    formatter_1.fmt.step(stepNum, 'Downloading testlib.h');
    const testlibUrl = 'https://raw.githubusercontent.com/MikeMirzayanov/testlib/master/testlib.h';
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Source: ${formatter_1.fmt.dim('github.com/MikeMirzayanov/testlib')}`);
    const testlibContent = await (0, testlib_download_1.downloadFile)(testlibUrl);
    formatter_1.fmt.stepComplete('Downloaded successfully');
    return testlibContent;
}
function stepSaveTestlibToDirectory(stepNum, testlibContent) {
    formatter_1.fmt.step(stepNum, 'Saving to Current Directory');
    const targetPath = path_1.default.join(process.cwd(), 'testlib.h');
    fs_1.default.writeFileSync(targetPath, testlibContent, 'utf-8');
    formatter_1.fmt.stepComplete('File saved');
}
// ============================================================================
// VALIDATION STEPS
// ============================================================================
function stepValidateConfigForValidator(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Validating Configuration');
    (0, validator_1.ensureValidatorExists)(config.validator);
    (0, testset_1.ensureTestsetsExist)(config.testsets);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Validator: ${formatter_1.fmt.highlight(config.validator.source)} ${formatter_1.fmt.dim('(C++)')}`);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Testsets: ${formatter_1.fmt.highlight(config.testsets.length.toString())}`);
    formatter_1.fmt.stepComplete('Configuration validated');
}
async function stepCompileValidator(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Compiling Validator');
    await (0, validator_1.compileValidator)(config.validator);
    formatter_1.fmt.stepComplete('Validator compiled');
}
async function stepValidateAllTestsets(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Validating All Testsets');
    await (0, validator_1.validateAllTestsets)(config.validator, config.testsets);
    formatter_1.fmt.stepComplete('All testsets validated');
}
async function stepValidateSingleTest(stepNum, config, testsetName, testIndex) {
    formatter_1.fmt.step(stepNum, `Validating Test ${testIndex}`);
    await (0, validator_1.validateSingleTest)(config.validator, testsetName, testIndex);
    formatter_1.fmt.stepComplete(`Test ${testIndex} validated`);
}
async function stepValidateGroup(stepNum, config, testset, groupName) {
    formatter_1.fmt.step(stepNum, `Validating Group '${groupName}'`);
    await (0, validator_1.validateGroup)(config.validator, testset, groupName);
    formatter_1.fmt.stepComplete(`Group '${groupName}' validated`);
}
async function stepValidateTestset(stepNum, config, testsetName) {
    formatter_1.fmt.step(stepNum, 'Validating Tests');
    await (0, validator_1.validateTestset)(config.validator, testsetName);
    formatter_1.fmt.stepComplete('Tests validated');
}
// ============================================================================
// GENERATION STEPS
// ============================================================================
function stepValidateConfigForGeneration(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Validating Configuration');
    (0, testset_1.ensureTestsetsExist)(config.testsets);
    (0, generator_1.ensureGeneratorsExist)(config.generators);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Testsets: ${formatter_1.fmt.highlight(config.testsets.length.toString())}`);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Generators: ${formatter_1.fmt.highlight(config.generators.length.toString())}`);
    formatter_1.fmt.stepComplete('Configuration validated');
}
async function stepCompileGeneratorsForTestsets(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Compiling Generators');
    await (0, generator_1.compileGeneratorsForTestsets)(config.testsets, config.generators);
    formatter_1.fmt.stepComplete('Generators compiled');
}
async function stepGenerateAllTestsets(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Generating Tests for All Testsets');
    await (0, testset_1.generateAllTestsets)(config.testsets, config.generators);
    formatter_1.fmt.stepComplete('All testsets generated');
}
async function stepCompileGeneratorsForSingleTest(stepNum, config, testset, testIndex) {
    formatter_1.fmt.step(stepNum, 'Compiling Generators');
    const commands = (0, testset_1.getGeneratorCommands)(testset);
    const command = commands[testIndex - 1];
    await (0, generator_1.compileAllGenerators)([command], config.generators);
    formatter_1.fmt.stepComplete('Generators compiled');
}
async function stepGenerateSingleTest(stepNum, config, testset, testIndex) {
    formatter_1.fmt.step(stepNum, `Generating Test ${testIndex}`);
    await (0, testset_1.generateSingleTest)(testset, testIndex, config.generators);
    formatter_1.fmt.stepComplete(`Test ${testIndex} generated`);
}
async function stepCompileGeneratorsForGroup(stepNum, config, testset, groupName) {
    formatter_1.fmt.step(stepNum, 'Compiling Generators');
    const allCommands = (0, testset_1.getGeneratorCommands)(testset);
    const groupCommands = allCommands.filter(cmd => groupName === 'all' || cmd.group === groupName);
    await (0, generator_1.compileAllGenerators)(groupCommands, config.generators);
    formatter_1.fmt.stepComplete('Generators compiled');
}
async function stepGenerateTestsForGroup(stepNum, config, testset, groupName) {
    formatter_1.fmt.step(stepNum, `Generating Group '${groupName}'`);
    await (0, testset_1.generateTestsForGroup)(testset, groupName, config.generators);
    formatter_1.fmt.stepComplete(`Group '${groupName}' generated`);
}
async function stepCompileGeneratorsForTestset(stepNum, config, testset) {
    formatter_1.fmt.step(stepNum, 'Compiling Generators');
    const commands = (0, testset_1.getGeneratorCommands)(testset);
    await (0, generator_1.compileAllGenerators)(commands, config.generators);
    formatter_1.fmt.stepComplete('Generators compiled');
}
async function stepGenerateTestsForTestset(stepNum, config, testset) {
    formatter_1.fmt.step(stepNum, 'Generating Tests');
    await (0, testset_1.generateTestsForTestset)(testset, config.generators);
    formatter_1.fmt.stepComplete('Tests generated');
}
// ============================================================================
// SOLUTION STEPS
// ============================================================================
function stepValidateConfigForSolutions(stepNum, config, matchingSolutions) {
    formatter_1.fmt.step(stepNum, 'Validating Configuration');
    (0, solution_1.validateSolutionsExist)(config.solutions);
    (0, testset_1.ensureTestsetsExist)(config.testsets);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Solutions: ${formatter_1.fmt.highlight(matchingSolutions.length.toString())}`);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Testsets: ${formatter_1.fmt.highlight(config.testsets.length.toString())}`);
    formatter_1.fmt.stepComplete('Configuration validated');
}
async function stepCompileSolutions(stepNum, solutions) {
    formatter_1.fmt.step(stepNum, 'Compiling Solutions');
    await (0, solution_1.compileAllSolutions)(solutions);
    formatter_1.fmt.stepComplete('Solutions compiled');
}
async function stepRunSolutionsOnAllTestsets(stepNum, config, solutions) {
    formatter_1.fmt.step(stepNum, 'Running Solutions on All Testsets');
    for (const solution of solutions) {
        try {
            await (0, solution_1.runSolutionOnAllTestsets)(solution, config, config.testsets);
        }
        catch {
            //
        }
    }
    formatter_1.fmt.stepComplete('All solutions completed');
}
async function stepRunSolutionsOnTestset(stepNum, config, solutions, testsetName) {
    formatter_1.fmt.step(stepNum, `Running Solutions on Testset ${testsetName}`);
    for (const solution of solutions) {
        try {
            await (0, solution_1.runSolutionOnTestset)(solution, config, testsetName);
        }
        catch {
            //
        }
    }
    formatter_1.fmt.stepComplete('Solutions completed');
}
async function stepRunSolutionsOnTest(stepNum, config, solutions, testsetName, testIndex) {
    formatter_1.fmt.step(stepNum, `Running Solutions on Test ${testIndex}`);
    for (const solution of solutions) {
        await (0, solution_1.runSolutionOnSingleTest)(solution, config, testsetName, testIndex);
    }
    formatter_1.fmt.stepComplete('Solutions completed');
}
async function stepRunSolutionsOnGroup(stepNum, config, solutions, testset, groupName) {
    formatter_1.fmt.step(stepNum, `Running Solutions on Group ${groupName}`);
    for (const solution of solutions) {
        await (0, solution_1.runSolutionOnGroup)(solution, config, testset, groupName);
    }
    formatter_1.fmt.stepComplete('Solutions completed');
}
// ============================================================================
// CHECKER STEPS
// ============================================================================
async function stepCompileChecker(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Compiling Checker');
    (0, checker_1.ensureCheckerExists)(config.checker);
    await (0, checker_1.compileChecker)(config.checker);
    formatter_1.fmt.stepComplete('Checker compiled');
}
function stepValidateConfigForChecker(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Validating Checker Configuration');
    (0, checker_1.ensureCheckerExists)(config.checker);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Checker: ${formatter_1.fmt.highlight(config.checker.source)} ${formatter_1.fmt.dim('(C++)')}`);
    formatter_1.fmt.stepComplete('Checker configuration validated');
}
async function stepTestChecker(stepNum) {
    formatter_1.fmt.step(stepNum, 'Testing Checker');
    await (0, checker_1.testCheckerItself)();
    formatter_1.fmt.stepComplete('Checker tests passed');
}
// ============================================================================
// TEST SOLUTION STEPS
// ============================================================================
function stepValidateConfigForSolutionTest(stepNum, what) {
    formatter_1.fmt.step(stepNum, 'Validating Configuration');
    const config = (0, utils_1.readConfigFile)();
    (0, solution_1.validateSolutionsExist)(config.solutions);
    (0, solution_1.ensureMainSolutionExists)(config.solutions);
    const mainSolution = (0, solution_1.getMainSolution)(config.solutions);
    const targetSolution = config.solutions.find(s => s.name === what);
    if (!targetSolution) {
        throw new Error(`No solution named "${what}" found.`);
    }
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Main solution: ${formatter_1.fmt.primary(mainSolution.name)} ${formatter_1.fmt.dim(`(${mainSolution.tag})`)}`);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Target solution: ${formatter_1.fmt.highlight(targetSolution.name)} ${formatter_1.fmt.dim(`(${targetSolution.tag})`)}`);
    formatter_1.fmt.stepComplete('Configuration validated');
    return { mainSolution, targetSolution };
}
async function stepTestSolutionBehavior(stepNum, solutionName) {
    formatter_1.fmt.step(stepNum, 'Testing Solution Behavior');
    await (0, solution_1.testSolutionAgainstMainCorrect)(solutionName);
    formatter_1.fmt.stepComplete('Solution verified');
}
// ============================================================================
// FULL VERIFICATION STEPS
// ============================================================================
async function stepGenerateTestsForVerification(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Generating Tests');
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Found ${formatter_1.fmt.highlight(config.generators.length.toString())} generator(s)`);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Found ${formatter_1.fmt.highlight(config.testsets.length.toString())} testset(s)`);
    await (0, testset_1.generateAllTestsets)(config.testsets, config.generators);
    formatter_1.fmt.stepComplete('All tests generated successfully');
}
async function stepTestValidator(stepNum) {
    formatter_1.fmt.step(stepNum, 'Testing Validator');
    await (0, validator_1.testValidatorItself)();
    formatter_1.fmt.stepComplete('Validator tests passed');
}
async function stepValidateGeneratedTests(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Validating Generated Tests');
    await (0, validator_1.validateAllTestsets)(config.validator, config.testsets);
    formatter_1.fmt.stepComplete('All generated tests are valid');
}
async function stepCompileSolutionsForVerification(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Compiling Solutions');
    (0, solution_1.validateSolutionsExist)(config.solutions);
    (0, solution_1.ensureMainSolutionExists)(config.solutions);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Found ${formatter_1.fmt.highlight(config.solutions.length.toString())} solution(s)`);
    await (0, solution_1.compileAllSolutions)(config.solutions);
    formatter_1.fmt.stepComplete('Solutions compiled');
}
async function stepRunSolutionsForVerification(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Running Solutions');
    const mainSolution = (0, solution_1.getMainSolution)(config.solutions);
    const otherSolutions = config.solutions.filter(s => s.name !== mainSolution.name);
    formatter_1.fmt.info(`  ${formatter_1.fmt.infoIcon()} Main solution: ${formatter_1.fmt.primary(mainSolution.name)} ${formatter_1.fmt.dim(`(${mainSolution.tag})`)}`);
    await (0, solution_1.runSolutionOnAllTestsets)(mainSolution, config, config.testsets);
    let someFailed = false;
    for (const solution of otherSolutions) {
        try {
            await (0, solution_1.runSolutionOnAllTestsets)(solution, config, config.testsets);
        }
        catch {
            someFailed = true;
        }
    }
    if (someFailed) {
        formatter_1.fmt.warning('  Some Solutions Failed, may be expected');
    }
    formatter_1.fmt.stepComplete('All solutions have run');
}
async function stepVerifySolutionsAgainstMainCorrect(stepNum, config) {
    formatter_1.fmt.step(stepNum, 'Verifying Solutions Against Main Correct');
    const mainSolution = (0, solution_1.getMainSolution)(config.solutions);
    const otherSolutions = config.solutions.filter(s => s.name !== mainSolution.name);
    let didFail = false;
    for (const solution of otherSolutions) {
        formatter_1.fmt.log(`    ${formatter_1.fmt.dim('→')} Checking ${formatter_1.fmt.highlight(solution.name)} ${formatter_1.fmt.dim(`(${solution.tag})`)}`);
        try {
            await (0, solution_1.startTheComparisonProcess)(config.checker, mainSolution, solution, config.testsets);
            formatter_1.fmt.success(`    ${formatter_1.fmt.dim('→')} ${formatter_1.fmt.checkmark()} ${formatter_1.fmt.highlight(solution.name)} Behaves as expected`);
        }
        catch (error) {
            didFail = true;
            (0, utils_1.logError)(error, 4);
        }
    }
    if (didFail) {
        throw new Error('Some solutions did not behave as expected');
    }
    else {
        formatter_1.fmt.success(`      ${formatter_1.fmt.checkmark()} Behaves as expected`);
    }
    formatter_1.fmt.stepComplete('All solutions verified');
}
//# sourceMappingURL=steps.js.map