"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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tasksAddCommand = tasksAddCommand;
exports.tasksRemoveCommand = tasksRemoveCommand;
exports.tasksLsCommand = tasksLsCommand;
exports.tasksPushCommand = tasksPushCommand;
exports.tasksUpdateCommand = tasksUpdateCommand;
const crypto = __importStar(require("node:crypto"));
const readline = __importStar(require("node:readline/promises"));
const node_process_1 = require("node:process");
const chalk_1 = __importDefault(require("chalk"));
const tasks_1 = require("../tasks");
const cron_1 = require("../cron");
const logger_1 = require("../logger");
const config_1 = require("../config");
const providers_1 = require("../providers");
// ─── Shared helpers ───────────────────────────────────────────────────────────
function dim(s) {
    return chalk_1.default.dim(s);
}
function hint(s) {
    return chalk_1.default.dim(`(${s})`);
}
async function ask(rl, question, defaultVal = '', required = false) {
    const suffix = defaultVal ? chalk_1.default.dim(` [${defaultVal}]`) : '';
    while (true) {
        const raw = await rl.question(`  ${question}${suffix}: `);
        const val = raw.trim() || defaultVal;
        if (required && !val) {
            console.log(chalk_1.default.yellow('  This field is required.'));
            continue;
        }
        return val;
    }
}
async function choose(rl, question, options, defaultVal) {
    const opts = options
        .map((o) => (o === defaultVal ? chalk_1.default.cyan(o) : o))
        .join(chalk_1.default.dim(' | '));
    while (true) {
        const raw = await rl.question(`  ${question} ${dim(`[${opts}]`)}: `);
        const val = raw.trim() || defaultVal;
        if (!options.includes(val)) {
            console.log(chalk_1.default.yellow(`  Choose one of: ${options.join(', ')}`));
            continue;
        }
        return val;
    }
}
function validateCron(expr) {
    try {
        (0, cron_1.parseCron)(expr);
        return true;
    }
    catch {
        return false;
    }
}
async function askCron(rl, defaultVal = '') {
    const suffix = defaultVal ? chalk_1.default.dim(` [${defaultVal}]`) : '';
    while (true) {
        const raw = await rl.question(`  Cron expression ${hint('5-field, blank for one-shot')}${suffix}: `);
        const val = raw.trim() || defaultVal;
        if (!val)
            return '';
        if (validateCron(val))
            return val;
        console.log(chalk_1.default.yellow('  Invalid cron expression. Use 5 fields: minute hour day month weekday'));
    }
}
async function collectTaskFields(rl, defaults = {}) {
    const title = await ask(rl, 'Title', defaults.title || '', true);
    const description = await ask(rl, 'Description', defaults.description || '');
    const type = (await choose(rl, 'Type', ['code', 'non-code'], defaults.type || 'code'));
    const priorityRaw = await ask(rl, `Priority ${hint('1=urgent 2=high 3=normal 4=low, blank=none')}`, defaults.priority ? String(defaults.priority) : '');
    const priority = priorityRaw ? parseInt(priorityRaw, 10) : undefined;
    const dueDate = await ask(rl, `Due date ${hint('YYYY-MM-DD, blank=none')}`, defaults.dueDate || '');
    const tagsRaw = await ask(rl, `Extra tags ${hint('comma-separated, blank=none')}`, (defaults.tags ?? []).join(','));
    const tags = tagsRaw ? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean) : undefined;
    const listId = await ask(rl, `List / project ID ${hint('blank=use env default')}`, defaults.listId || '');
    const cron = await askCron(rl, defaults.cron || '');
    return {
        title,
        description,
        type,
        ...(priority !== undefined ? { priority } : {}),
        ...(dueDate ? { dueDate } : {}),
        ...(tags && tags.length > 0 ? { tags } : {}),
        ...(listId ? { listId } : {}),
        ...(cron ? { cron } : {}),
    };
}
// ─── Table rendering ──────────────────────────────────────────────────────────
function printTasksTable(tasks) {
    const idW = 4;
    const titleW = Math.max(5, ...tasks.map((t) => t.title.length));
    const typeW = 8;
    const cronW = Math.max(4, ...tasks.map((t) => (t.cron || '—').length));
    const prioW = 8;
    const header = `  ${chalk_1.default.bold('ID'.padEnd(idW))}  ` +
        `${chalk_1.default.bold('Title'.padEnd(titleW))}  ` +
        `${chalk_1.default.bold('Type'.padEnd(typeW))}  ` +
        `${chalk_1.default.bold('Priority'.padEnd(prioW))}  ` +
        chalk_1.default.bold('Cron'.padEnd(cronW));
    const sep = `  ${'─'.repeat(idW)}  ` +
        `${'─'.repeat(titleW)}  ` +
        `${'─'.repeat(typeW)}  ` +
        `${'─'.repeat(prioW)}  ` +
        '─'.repeat(cronW);
    console.log(header);
    console.log(sep);
    const prioNames = { 1: 'urgent', 2: 'high', 3: 'normal', 4: 'low' };
    tasks.forEach((t, i) => {
        const id = chalk_1.default.cyan(String(i + 1).padStart(idW));
        const title = t.title.padEnd(titleW);
        const type = t.type === 'code' ? chalk_1.default.green(t.type.padEnd(typeW)) : chalk_1.default.yellow(t.type.padEnd(typeW));
        const prio = (t.priority ? prioNames[t.priority] || String(t.priority) : '—').padEnd(prioW);
        const cron = (t.cron || '—').padEnd(cronW);
        console.log(`  ${id}  ${title}  ${type}  ${prio}  ${cron}`);
    });
}
async function pickTaskIndex(rl, tasks) {
    while (true) {
        const raw = await rl.question(`\n  Select task ${dim('[1]')}: `);
        const val = raw.trim() || '1';
        const n = parseInt(val, 10);
        if (n >= 1 && n <= tasks.length)
            return n - 1;
        console.log(chalk_1.default.yellow(`  Enter a number between 1 and ${tasks.length}.`));
    }
}
// ─── Commands ─────────────────────────────────────────────────────────────────
async function tasksAddCommand() {
    console.log(chalk_1.default.bold('\nAdd a local task\n'));
    const rl = readline.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
    try {
        const fields = await collectTaskFields(rl);
        const task = {
            id: crypto.randomUUID(),
            ...fields,
        };
        const tasks = (0, tasks_1.readTasksFile)();
        tasks.push(task);
        (0, tasks_1.writeTasksFile)(tasks);
        console.log();
        logger_1.logger.success(`Task added: "${task.title}"${task.cron ? ` (cron: ${task.cron})` : ''}`);
    }
    finally {
        rl.close();
    }
}
async function tasksRemoveCommand(id) {
    const tasks = (0, tasks_1.readTasksFile)();
    if (tasks.length === 0) {
        logger_1.logger.warn('No local tasks found');
        return;
    }
    let idx;
    if (id !== undefined) {
        idx = parseInt(id, 10) - 1;
    }
    else {
        console.log();
        printTasksTable(tasks);
        console.log();
        const rl = readline.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
        try {
            idx = await pickTaskIndex(rl, tasks);
        }
        finally {
            rl.close();
        }
    }
    if (idx < 0 || idx >= tasks.length) {
        logger_1.logger.error(`Invalid ID: ${(idx + 1)}. Valid range: 1–${tasks.length}`);
        process.exit(1);
    }
    const removed = tasks.splice(idx, 1)[0];
    (0, tasks_1.writeTasksFile)(tasks);
    logger_1.logger.success(`Removed task: "${removed.title}"`);
}
async function tasksLsCommand() {
    const tasks = (0, tasks_1.readTasksFile)();
    if (tasks.length === 0) {
        logger_1.logger.warn('No local tasks found');
        logger_1.logger.info('Use "aidev tasks add" to create one.');
        return;
    }
    logger_1.logger.info(`Local tasks (${tasks.length}):`);
    console.log();
    printTasksTable(tasks);
    console.log();
}
async function tasksPushCommand(envPath) {
    const tasks = (0, tasks_1.readTasksFile)();
    if (tasks.length === 0) {
        logger_1.logger.warn('No local tasks found in aidev.tasks.json');
        logger_1.logger.info('Use "aidev tasks add" to create one.');
        return;
    }
    const config = (0, config_1.loadConfig)(envPath);
    const provider = (0, providers_1.createProvider)(config);
    let nonCodeProvider;
    if (config.nonCodeTag) {
        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');
    }
    const result = await (0, tasks_1.processLocalTasks)(config, provider, nonCodeProvider);
    logger_1.logger.info(`Local tasks: ${result.pushed} pushed, ${result.skipped} skipped`);
}
async function tasksUpdateCommand(id) {
    const tasks = (0, tasks_1.readTasksFile)();
    if (tasks.length === 0) {
        logger_1.logger.warn('No local tasks found');
        return;
    }
    let idx;
    const rl = readline.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
    try {
        if (id !== undefined) {
            idx = parseInt(id, 10) - 1;
        }
        else {
            console.log();
            printTasksTable(tasks);
            console.log();
            idx = await pickTaskIndex(rl, tasks);
        }
        if (idx < 0 || idx >= tasks.length) {
            logger_1.logger.error(`Invalid ID: ${(idx + 1)}. Valid range: 1–${tasks.length}`);
            process.exit(1);
        }
        const existing = tasks[idx];
        console.log(chalk_1.default.bold(`\nUpdate task: "${existing.title}"\n`));
        const fields = await collectTaskFields(rl, existing);
        tasks[idx] = {
            id: existing.id,
            ...fields,
            ...(existing.lastPushedAt !== undefined ? { lastPushedAt: existing.lastPushedAt } : {}),
        };
        (0, tasks_1.writeTasksFile)(tasks);
        console.log();
        logger_1.logger.success(`Task updated: "${tasks[idx].title}"`);
    }
    finally {
        rl.close();
    }
}
//# sourceMappingURL=tasks.js.map