import { Args, Flags } from '@oclif/core';
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
import { styles } from '../../lib/styles.js';
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
export default class TicketReassign extends PMOCommand {
    static description = 'Reassign ticket(s) to a different agent';
    static examples = [
        '<%= config.bin %> <%= command.id %>',
        '<%= config.bin %> <%= command.id %> TKT-001 alice',
        '<%= config.bin %> <%= command.id %> --bulk --to alice',
        '<%= config.bin %> <%= command.id %> --bulk --from bob --to alice',
        '<%= config.bin %> <%= command.id %> --json  # Output choices as JSON',
    ];
    static args = {
        ticketId: Args.string({
            description: 'Ticket ID - prompts with dropdown if not provided',
            required: false,
        }),
        assignee: Args.string({
            description: 'Target agent name',
            required: false,
        }),
    };
    static flags = {
        ...pmoBaseFlags,
        to: Flags.string({
            description: 'Target agent name (for bulk mode)',
        }),
        from: Flags.string({
            description: 'Filter tickets by current assignee (bulk mode)',
        }),
        bulk: Flags.boolean({
            char: 'b',
            description: 'Enable bulk mode to reassign multiple tickets',
            default: false,
        }),
        force: Flags.boolean({
            char: 'f',
            description: 'Skip confirmation prompt',
            default: false,
        }),
    };
    async execute() {
        const { args, flags } = await this.parse(TicketReassign);
        const projectId = flags.project;
        // Check if JSON output mode is active
        const jsonMode = shouldOutputJson(flags);
        // Get all tickets
        const allTickets = await this.storage.listTickets(projectId);
        if (allTickets.length === 0) {
            if (jsonMode) {
                outputErrorAsJson('NO_TICKETS', 'No tickets found.', createMetadata('ticket reassign', flags));
                return;
            }
            this.log(styles.warning('No tickets found.'));
            return;
        }
        // Get unique assignees from tickets
        const assignees = new Set();
        for (const ticket of allTickets) {
            if (ticket.assignee) {
                assignees.add(ticket.assignee);
            }
        }
        // Also get agents from workspace if available
        const db = this.storage.db;
        try {
            const agents = db.prepare(`SELECT name FROM agents`).all();
            for (const agent of agents) {
                assignees.add(agent.name);
            }
        }
        catch {
            // agents table might not exist, ignore
        }
        // Bulk mode
        if (flags.bulk) {
            await this.executeBulk(allTickets, Array.from(assignees), flags);
            return;
        }
        // Single ticket mode
        let ticketId = args.ticketId;
        if (!ticketId) {
            const selected = await this.selectFromList({
                message: 'Select ticket to reassign:',
                items: allTickets,
                getName: (t) => `${t.id} - ${t.title} (${t.statusName})`,
                getValue: (t) => t.id,
                getCommand: (t) => `prlt ticket reassign ${t.id}${projectId ? ` -P ${projectId}` : ''} --json`,
                jsonMode: jsonMode ? { flags, commandName: 'ticket reassign' } : null,
            });
            if (!selected) {
                return;
            }
            ticketId = selected;
        }
        // Get ticket
        const ticket = await this.storage.getTicket(ticketId);
        if (!ticket) {
            this.error(`Ticket "${ticketId}" not found.`);
        }
        // Get target assignee
        let targetAssignee = args.assignee || flags.to;
        if (!targetAssignee) {
            const jsonModeConfig = jsonMode ? { flags, commandName: 'ticket reassign' } : null;
            const { assignee } = await this.prompt([{
                    type: 'list',
                    name: 'assignee',
                    message: `Reassign ${ticketId} to:`,
                    choices: [
                        { name: 'None (unassign)', value: '__none__', command: `prlt ticket reassign ${ticketId} none${projectId ? ` -P ${projectId}` : ''} --json` },
                        ...Array.from(assignees).sort().map(a => ({
                            name: a === ticket.assignee ? `${a} (current)` : a,
                            value: a,
                            command: `prlt ticket reassign ${ticketId} ${a}${projectId ? ` -P ${projectId}` : ''} --json`,
                        })),
                        { name: '── Enter custom name ──', value: '__custom__', command: `prlt ticket reassign ${ticketId} <name>${projectId ? ` -P ${projectId}` : ''} --json` },
                    ],
                }], jsonModeConfig);
            if (assignee === '__custom__') {
                const { customAssignee } = await this.prompt([{
                        type: 'input',
                        name: 'customAssignee',
                        message: 'Enter agent/assignee name:',
                        validate: (input) => input.length > 0 || 'Name is required',
                    }], jsonModeConfig);
                targetAssignee = customAssignee;
            }
            else if (assignee === '__none__') {
                targetAssignee = undefined;
            }
            else {
                targetAssignee = assignee;
            }
        }
        // Handle special values
        if (targetAssignee === 'none' || targetAssignee === 'unassigned') {
            targetAssignee = undefined;
        }
        // Validate agent name if provided directly (not through interactive prompt)
        if (targetAssignee && (args.assignee || flags.to)) {
            try {
                const workspaceInfo = getWorkspaceInfo();
                const agent = workspaceInfo.agents.find(a => a.name === targetAssignee);
                if (!agent) {
                    this.error(`Agent "${targetAssignee}" not found. Run 'prlt agent list' to see available agents.`);
                }
            }
            catch {
                // Not in a workspace or agents table doesn't exist - skip validation
            }
        }
        // Check if same
        if (targetAssignee === ticket.assignee) {
            this.log(styles.muted(`Ticket "${ticketId}" is already assigned to "${targetAssignee || 'none'}".`));
            return;
        }
        // Update ticket
        await this.storage.updateTicket(ticketId, { assignee: targetAssignee || undefined });
        // Auto-export
        await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
        const action = targetAssignee ? `reassigned to ${targetAssignee}` : 'unassigned';
        this.log(styles.success(`\n✅ Ticket ${styles.emphasis(ticketId)} ${action}`));
        this.log(styles.muted(`   Title: ${ticket.title}`));
        if (ticket.assignee) {
            this.log(styles.muted(`   Previous: ${ticket.assignee}`));
        }
    }
    async executeBulk(allTickets, assigneesList, flags) {
        const jsonMode = shouldOutputJson(flags);
        this.log(styles.emphasis('👤 Reassign Tickets\n'));
        // Filter tickets if --from specified
        let filteredTickets = allTickets;
        if (flags.from) {
            if (flags.from === 'none' || flags.from === 'unassigned') {
                filteredTickets = allTickets.filter(t => !t.assignee);
            }
            else {
                filteredTickets = allTickets.filter(t => t.assignee === flags.from);
            }
        }
        if (filteredTickets.length === 0) {
            this.log(styles.warning('No tickets found matching filter.'));
            return;
        }
        // Select tickets to reassign
        const jsonModeConfig = jsonMode ? { flags: flags, commandName: 'ticket reassign' } : null;
        const { selectedTickets } = await this.prompt([{
                type: 'checkbox',
                name: 'selectedTickets',
                message: 'Select tickets to reassign:',
                choices: filteredTickets.map(t => ({
                    name: `${t.id} - ${t.title}  [Assignee: ${t.assignee || '(none)'}]`,
                    value: t.id,
                })),
            }], jsonModeConfig);
        if (selectedTickets.length === 0) {
            this.log(styles.muted('No tickets selected.'));
            return;
        }
        // Select target assignee
        let targetAssignee = flags.to;
        if (targetAssignee === undefined) {
            const { assignee } = await this.prompt([{
                    type: 'list',
                    name: 'assignee',
                    message: 'Reassign to which agent?',
                    choices: [
                        { name: 'None (unassign)', value: '__none__', command: '' },
                        ...assigneesList.sort().map(a => ({
                            name: a,
                            value: a,
                            command: `prlt ticket reassign --bulk --to ${a} --json`,
                        })),
                        { name: '── Enter custom name ──', value: '__custom__', command: '' },
                    ],
                }], jsonModeConfig);
            if (assignee === '__custom__') {
                const { customAssignee } = await this.prompt([{
                        type: 'input',
                        name: 'customAssignee',
                        message: 'Enter agent/assignee name:',
                        validate: (input) => input.length > 0 || 'Name is required',
                    }], jsonModeConfig);
                targetAssignee = customAssignee;
            }
            else if (assignee === '__none__') {
                targetAssignee = undefined;
            }
            else {
                targetAssignee = assignee;
            }
        }
        // Handle special values
        if (targetAssignee === 'none' || targetAssignee === 'unassigned') {
            targetAssignee = undefined;
        }
        // Validate agent name if provided directly via --to flag (not through interactive prompt)
        if (targetAssignee && flags.to) {
            try {
                const workspaceInfo = getWorkspaceInfo();
                const agent = workspaceInfo.agents.find(a => a.name === targetAssignee);
                if (!agent) {
                    this.error(`Agent "${targetAssignee}" not found. Run 'prlt agent list' to see available agents.`);
                }
            }
            catch {
                // Not in a workspace or agents table doesn't exist - skip validation
            }
        }
        // Confirmation
        if (!flags.force) {
            const assigneeLabel = targetAssignee || 'None (unassigning)';
            this.log(styles.primary('\nWill reassign to:'));
            this.log(styles.primary(`  → ${assigneeLabel}\n`));
            this.log(styles.primary('Tickets:'));
            for (const ticketId of selectedTickets) {
                const ticket = filteredTickets.find(t => t.id === ticketId);
                this.log(styles.primary(`  • ${ticketId}: ${ticket?.title}`));
            }
            this.log('');
            const { confirm } = await this.prompt([{
                    type: 'list',
                    name: 'confirm',
                    message: 'Continue?',
                    choices: [
                        { name: 'No, cancel', value: false, command: '' },
                        { name: 'Yes, reassign tickets', value: true, command: `prlt ticket reassign --bulk --to ${targetAssignee || 'none'} --force --json` }
                    ],
                    default: 0
                }], jsonModeConfig);
            if (!confirm) {
                this.log(styles.muted('Operation cancelled.'));
                return;
            }
        }
        this.log('');
        // Reassign each ticket
        let successCount = 0;
        let failCount = 0;
        // Process sequentially for clear success/failure logging
        for (const ticketId of selectedTickets) {
            try {
                // eslint-disable-next-line no-await-in-loop
                await this.storage.updateTicket(ticketId, { assignee: targetAssignee || undefined });
                const action = targetAssignee ? `Reassigned to ${targetAssignee}` : 'Unassigned';
                this.log(styles.success(`${ticketId}: ${action}`));
                successCount++;
            }
            catch (error) {
                this.log(styles.error(`Failed to reassign ${ticketId}: ${error instanceof Error ? error.message : String(error)}`));
                failCount++;
            }
        }
        // Auto-export to kanban.md
        await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
        // Summary
        this.log('');
        if (successCount > 0) {
            const action = targetAssignee ? 'Reassigned' : 'Unassigned';
            this.log(styles.success(`${action} ${successCount} ticket(s)`));
        }
        if (failCount > 0) {
            this.log(styles.error(`Failed to reassign ${failCount} ticket(s)`));
        }
    }
}
//# sourceMappingURL=reassign.js.map