"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectTasks = selectTasks;
exports.reportTaskErrors = reportTaskErrors;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const types_1 = require("@playdrop/types");
const catalogue_1 = require("./catalogue");
const taskUtils_1 = require("./taskUtils");
const messages_1 = require("./messages");
function createDirectAppTask(htmlPath) {
    const rootDir = (0, node_path_1.dirname)(htmlPath);
    const name = (0, node_path_1.basename)(htmlPath, (0, node_path_1.extname)(htmlPath));
    return {
        kind: 'app',
        name,
        cataloguePath: 'direct upload',
        catalogueAbsolutePath: (0, node_path_1.join)(rootDir, 'catalogue.json'),
        catalogueDir: rootDir,
        filePath: htmlPath,
        relativeFile: (0, node_path_1.basename)(htmlPath),
        projectDir: rootDir,
        packageJsonPath: null,
        isTypescriptProject: false,
        hasValidateScript: false,
        hasFormatScript: false,
        displayName: undefined,
        description: undefined,
        type: undefined,
        emoji: undefined,
        color: undefined,
        surfaceTargets: [],
        assetSpecSupport: [],
        tags: [],
        missingMetadata: [],
        achievements: [],
        leaderboards: [],
        ownedAssets: [],
        license: types_1.DEFAULT_CONTENT_LICENSE,
        uses: { assets: [], packs: [] },
        graph: { relations: [] },
    };
}
function selectTasks(pathOrName) {
    const warnings = new Set();
    const errors = [];
    const absolute = (0, node_path_1.resolve)(pathOrName);
    if ((0, node_fs_1.existsSync)(absolute)) {
        const stats = (0, node_fs_1.statSync)(absolute);
        if (stats.isDirectory()) {
            const rootCataloguePath = (0, node_path_1.join)(absolute, 'catalogue.json');
            if (!(0, node_fs_1.existsSync)(rootCataloguePath)) {
                errors.push({
                    type: 'catalogue-missing',
                    message: `catalogue.json not found in ${absolute}`,
                    directory: absolute,
                });
                return { tasks: [], warnings, errors, resolution: 'directory' };
            }
            const { apps, assetSpecs, assets, assetPacks, warnings: rawWarnings, errors: catalogueErrors } = (0, catalogue_1.resolveCatalogueEntries)(absolute);
            if (catalogueErrors.length > 0) {
                catalogueErrors.forEach(message => {
                    errors.push({
                        type: 'invalid-catalogue',
                        message,
                        help: ['Update the catalogue entry noted above and try again.'],
                    });
                });
                return { tasks: [], warnings, errors, resolution: 'directory' };
            }
            const taskList = [...assetSpecs, ...assets, ...apps, ...assetPacks];
            if (taskList.length === 0) {
                errors.push({
                    type: 'no-tasks',
                    message: `No publishable entries were found under ${absolute}.`,
                    help: ['Add child catalogue.json files or add apps, assetSpecs, assets, or assetPacks to the root catalogue.json, then rerun the command.'],
                    directory: absolute,
                });
                return { tasks: [], warnings, errors, resolution: 'directory' };
            }
            const metadataWarnings = (0, catalogue_1.formatMetadataWarnings)(rawWarnings);
            metadataWarnings.forEach(entry => warnings.add(entry));
            (0, taskUtils_1.addTaskWarnings)(warnings, taskList);
            return { tasks: taskList, warnings, errors, resolution: 'directory' };
        }
        if (stats.isFile()) {
            const extension = (0, node_path_1.extname)(absolute).toLowerCase();
            if (extension !== '.html') {
                errors.push({
                    type: 'unsupported-file',
                    message: 'Single-file commands only support app HTML files.',
                    help: [
                        'For assets and packs, run the command on the directory with catalogue.json.',
                        'Select the app HTML file you want to process, or provide the app name instead.',
                    ],
                });
                return { tasks: [], warnings, errors, resolution: 'file' };
            }
            const lookup = (0, catalogue_1.findAppTaskByFile)(absolute);
            lookup.errors.forEach(message => {
                errors.push({
                    type: 'invalid-catalogue',
                    message,
                    help: ['Update the catalogue entry noted above and try again.'],
                });
            });
            lookup.warnings.forEach(entry => warnings.add(entry));
            if (lookup.errors.length > 0) {
                return { tasks: [], warnings, errors, resolution: 'file' };
            }
            if (lookup.task) {
                (0, taskUtils_1.addTaskWarnings)(warnings, [lookup.task]);
                return { tasks: [lookup.task], warnings, errors, resolution: 'file' };
            }
            const directTask = createDirectAppTask(absolute);
            (0, taskUtils_1.addTaskWarnings)(warnings, [directTask]);
            return { tasks: [directTask], warnings, errors, resolution: 'file' };
        }
    }
    const lookup = (0, catalogue_1.resolveCatalogueEntries)(process.cwd(), { filterName: pathOrName });
    lookup.errors.forEach(message => {
        errors.push({
            type: 'invalid-catalogue',
            message,
            help: ['Update the catalogue entry noted above and try again.'],
        });
    });
    if (lookup.errors.length > 0) {
        return { tasks: [], warnings, errors, resolution: 'name' };
    }
    const candidates = [
        ...lookup.apps.filter(task => task.name === pathOrName),
        ...lookup.assetSpecs.filter(task => task.name === pathOrName),
        ...lookup.assets.filter(task => task.name === pathOrName),
        ...lookup.assetPacks.filter(task => task.name === pathOrName),
    ];
    if (candidates.length === 0) {
        errors.push({
            type: 'app-not-found',
            message: `"${pathOrName}" was not found in any catalogue.json under ${process.cwd()}.`,
            help: [
                'Ensure the catalogue entry exists and matches the name.',
                'You can also provide a directory path to process all apps, assets, and packs.',
            ],
        });
        return { tasks: [], warnings, errors, resolution: 'name' };
    }
    if (candidates.length > 1) {
        errors.push({
            type: 'multiple-apps',
            message: `Multiple catalogue entries share the name "${pathOrName}".`,
            help: [
                'Use a directory path to process all entries, or rename entries so names are unique.',
            ],
        });
        return { tasks: [], warnings, errors, resolution: 'name' };
    }
    const metadataWarnings = (0, catalogue_1.formatMetadataWarnings)(lookup.warnings);
    metadataWarnings.forEach(entry => warnings.add(entry));
    (0, taskUtils_1.addTaskWarnings)(warnings, candidates);
    return { tasks: [...candidates], warnings, errors, resolution: 'name' };
}
function reportTaskErrors(errors, command) {
    if (errors.length === 0) {
        return;
    }
    let sawInvalidCatalogue = false;
    for (const error of errors) {
        switch (error.type) {
            case 'catalogue-missing':
                if (error.directory) {
                    (0, messages_1.printCatalogueMissing)(error.directory, command);
                }
                break;
            case 'invalid-catalogue': {
                (0, messages_1.printErrorWithHelp)(error.message, error.help ?? ['Update the catalogue entry noted above and try again.'], { command, includeGeneralHelp: false });
                sawInvalidCatalogue = true;
                break;
            }
            case 'no-tasks': {
                (0, messages_1.printErrorWithHelp)(error.message, error.help ?? ['Add catalogue.json files to the project folders you want to process, then rerun the command.'], { command });
                break;
            }
            case 'unsupported-file': {
                (0, messages_1.printErrorWithHelp)(error.message, error.help ?? [
                    'For assets and packs, run the command on the directory with catalogue.json.',
                    'Select the app HTML file you want to process, or provide the app name instead.',
                ], { command });
                break;
            }
            case 'multiple-apps': {
                (0, messages_1.printErrorWithHelp)(error.message, error.help ?? [
                    'Ensure app names are unique across catalogue.json files.',
                    'Alternatively, provide the path to the HTML file you want to process.',
                ], { command });
                break;
            }
            case 'app-not-found': {
                (0, messages_1.printErrorWithHelp)(error.message, error.help ?? [
                    'Ensure the catalogue entry exists and matches the app name.',
                    'You can also provide the path to the app HTML file to process it directly.',
                ], { command });
                break;
            }
            default:
                break;
        }
    }
    if (sawInvalidCatalogue) {
        (0, messages_1.printInvalidCatalogue)(command);
    }
}
