#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const init_1 = require("./commands/init");
const run_1 = require("./commands/run");
const schedule_1 = require("./commands/schedule");
const tasks_1 = require("./commands/tasks");
const help_1 = require("./commands/help");
const stop_1 = require("./commands/stop");
const ui_1 = require("./commands/ui");
const config_1 = require("./config");
const providers_1 = require("./providers");
const ai_1 = require("./ai");
const tasks_2 = require("./tasks");
const logger_1 = require("./logger");
const hooks_1 = require("./hooks");
const accepted_1 = require("./commands/accepted");
const github_1 = require("./github");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { version } = require('../package.json');
const program = new commander_1.Command();
program
    .name('aidev')
    .description('AI-powered task executor — implements ClickUp tasks with Claude or Cursor')
    .version(version)
    .option('-e, --env <path>', 'path to env file (default: .env.aidev)');
program
    .command('init')
    .description('Create .env.aidev from template in current directory')
    .action(async () => {
    await (0, init_1.initCommand)();
});
program
    .command('help')
    .description('Show help')
    .action(() => {
    (0, help_1.helpCommand)();
});
async function runWithFilter(filter, taskId) {
    const validFilters = ['all', 'open', 'pending', 'review', 'tasks', 'accepted'];
    if (filter && !validFilters.includes(filter)) {
        logger_1.logger.error(`Unknown filter: ${filter}. Valid options: all, open, pending, review, tasks, accepted`);
        process.exit(1);
    }
    try {
        const { env } = program.opts();
        const config = (0, config_1.loadConfig)(env);
        const provider = (0, providers_1.createProvider)(config);
        // Handle "accepted" filter separately — no AI, just merge accepted PRs
        if (filter === 'accepted') {
            await (0, accepted_1.acceptedCommand)(config, provider);
            return;
        }
        // Single-task execution skips the local-push/non-code/accepted machinery:
        // the UI's "Execute" action targets exactly one remote task.
        let nonCodeProvider;
        if (config.nonCodeTag && !taskId) {
            const nonCodeConfig = {
                ...config,
                clickupTag: config.nonCodeTag,
                clickupTeamId: config.nonCodeClickupTeamId || config.clickupTeamId,
                jiraLabel: config.nonCodeTag,
                jiraProject: config.nonCodeJiraProject || config.jiraProject,
                linearLabel: config.nonCodeTag,
                linearTeamId: config.nonCodeLinearTeamId || config.linearTeamId,
                trelloLabel: config.nonCodeTag,
            };
            nonCodeProvider = (0, providers_1.createProvider)(nonCodeConfig, 'non-code');
        }
        if (!taskId) {
            // Always process local tasks (aidev.tasks.json)
            const localResult = await (0, tasks_2.processLocalTasks)(config, provider, nonCodeProvider);
            if (localResult.pushed > 0 || localResult.skipped > 0) {
                logger_1.logger.info(`Local tasks: ${localResult.pushed} pushed, ${localResult.skipped} skipped`);
            }
        }
        if (filter === 'tasks')
            return;
        const resolvedFilter = filter || 'all';
        const runners = (0, ai_1.createRunners)(config);
        const hooks = (0, hooks_1.loadHooks)(config.hooksPath);
        const hookVM = (0, hooks_1.createHookVM)(provider, runners);
        await (0, run_1.runCommand)(resolvedFilter, config, provider, runners, nonCodeProvider, hooks, hookVM, taskId);
        // Auto-merge accepted PRs if configured (requires gh CLI)
        if (!taskId && config.acceptedTag && (0, github_1.isGhInstalled)()) {
            await (0, accepted_1.acceptedCommand)(config, provider);
        }
    }
    catch (err) {
        logger_1.logger.error(String(err));
        process.exit(1);
    }
}
program
    .command('run [filter]', { isDefault: true })
    .description('Process tasks: all (default), open, pending, review, tasks, or accepted. Also checks review tasks for unresolved PR comments.')
    .option('--task <id>', 'process only the task with this provider id (skips local-task push, non-code, accepted, and review phases)')
    .option('--status <status>', 'alias for the positional filter — used by the aidev ui dashboard (open, pending, review, all)')
    .action(async (filter, opts) => {
    // --status is just a long-form alias for the positional filter so the UI's
    // Run screen can spawn `aidev run --status <status>` without worrying about
    // commander positional parsing. Explicit positional wins if both are given.
    const effectiveFilter = filter ?? opts.status;
    await runWithFilter(effectiveFilter, opts.task);
});
program
    .command('stop')
    .description('Stop any running aidev process in the current directory')
    .action(() => {
    (0, stop_1.stopCommand)();
});
program
    .command('ui')
    .description('Run the aidev dashboard UI (Nuxt app) on a local port')
    .option('--port <number>', 'port to bind on 127.0.0.1', '19422')
    .option('--prod', 'serve the built Nuxt output if present (falls back to dev)')
    .action(async (opts) => {
    try {
        await (0, ui_1.uiCommand)(opts);
    }
    catch (err) {
        logger_1.logger.error(String(err));
        process.exit(1);
    }
});
const scheduleCmd = program
    .command('schedule')
    .description('Manage cron schedule for aidev in current directory');
scheduleCmd
    .command('set [cron]')
    .description('Set cron schedule — interactive picker if no cron given. Pass -e <path> to embed a custom env file in the scheduled command.')
    .action(async (cron) => {
    // -e is defined on the root program and commander captures it there even
    // when it appears after the subcommand name, so read it from program.opts().
    const { env } = program.opts();
    const extraArgs = env ? ['-e', env] : [];
    await (0, schedule_1.scheduleSetCommand)(cron, extraArgs);
});
scheduleCmd
    .command('get')
    .description('Show all aidev cron schedules as a table')
    .action(async () => {
    await (0, schedule_1.scheduleGetCommand)();
});
scheduleCmd
    .command('remove [id]')
    .description('Remove an aidev cron schedule by table ID (interactive if omitted)')
    .action(async (id) => {
    await (0, schedule_1.scheduleRemoveCommand)(id ? parseInt(id, 10) : undefined);
});
scheduleCmd
    .command('fix')
    .description('Rebuild all aidev schedules with current binary paths and config')
    .action(() => {
    (0, schedule_1.scheduleFixCommand)();
});
const tasksCmd = program
    .command('tasks')
    .description('Manage local tasks (aidev.tasks.json)');
tasksCmd
    .command('add')
    .description('Add a new local task (interactive)')
    .action(async () => {
    await (0, tasks_1.tasksAddCommand)();
});
tasksCmd
    .command('remove [id]')
    .description('Remove a local task by table ID (interactive if omitted)')
    .action(async (id) => {
    await (0, tasks_1.tasksRemoveCommand)(id);
});
tasksCmd
    .command('ls')
    .description('List all local tasks')
    .action(async () => {
    await (0, tasks_1.tasksLsCommand)();
});
tasksCmd
    .command('update [id]')
    .description('Update a local task by table ID (interactive if omitted)')
    .action(async (id) => {
    await (0, tasks_1.tasksUpdateCommand)(id);
});
tasksCmd
    .command('push')
    .description('Publish all tasks from aidev.tasks.json to the configured provider')
    .action(async () => {
    const { env } = program.opts();
    try {
        await (0, tasks_1.tasksPushCommand)(env);
    }
    catch (err) {
        logger_1.logger.error(String(err));
        process.exit(1);
    }
});
program.parse(process.argv);
//# sourceMappingURL=cli.js.map