import chalk from 'chalk';
import * as fs from 'fs';
import * as path from 'path';
import { getUserAgentsDir } from '../lib/state.js';
import { getShimsDir } from '../lib/installations/shims.js';
import { ALL_AGENT_IDS, AGENTS } from '../lib/agents.js';
import { setHelpSections } from '../lib/help.js';
function aliasesFile() {
    return path.join(getUserAgentsDir(), 'aliases.json');
}
/** Names that would clobber an agent CLI shim or the `agents` binary itself. */
function reservedNames() {
    const reserved = new Set(['agents']);
    for (const id of ALL_AGENT_IDS)
        reserved.add(AGENTS[id].cliCommand);
    return reserved;
}
function readAliases() {
    const file = aliasesFile();
    if (!fs.existsSync(file))
        return {};
    try {
        const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
        return parsed && typeof parsed === 'object' ? parsed : {};
    }
    catch {
        return {};
    }
}
function writeAliases(map) {
    const file = aliasesFile();
    fs.mkdirSync(path.dirname(file), { recursive: true });
    fs.writeFileSync(file, JSON.stringify(map, null, 2) + '\n', 'utf-8');
}
function shimPath(name) {
    return path.join(getShimsDir(), name);
}
function generateAliasShim(name, expansion) {
    return `#!/bin/bash
# Auto-generated by agents-cli - do not edit
# Alias shim: ${name} -> agents ${expansion}
exec agents ${expansion} "$@"
`;
}
function isAliasShim(filePath) {
    try {
        const head = fs.readFileSync(filePath, 'utf-8').slice(0, 200);
        return head.includes('# Alias shim:');
    }
    catch {
        return false;
    }
}
/** Register `agents setup alias` under the parent `setup` command. */
export function registerAliasCommand(setupCmd) {
    const cmd = setupCmd
        .command('alias')
        .description('Create shorthand binaries that expand to `agents <subcommand>`');
    setHelpSections(cmd, {
        examples: `
      # Make \`teams\` run \`agents teams\`
      agents setup alias add teams

      # Shorthand for a longer expansion
      agents setup alias add sess sessions preview

      agents setup alias list
      agents setup alias remove teams
    `,
        notes: `
      Writes an executable shim into ~/.agents/.cache/shims/ (already on PATH after
      \`agents setup\`) and records it in ~/.agents/aliases.json.

      Names that collide with the agents binary or an agent CLI (claude, codex,
      grok, …) are refused. Top-level \`agents alias\` is gone — use this group.
    `,
    });
    cmd
        .command('add <name> [expansion...]')
        .description('Create an alias shim. If expansion is omitted, defaults to <name>.')
        .action((name, expansion) => {
        const expanded = expansion.length > 0 ? expansion.join(' ') : name;
        if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {
            console.error(chalk.red(`Invalid alias name "${name}". Use letters, digits, _ or -.`));
            process.exit(1);
        }
        if (reservedNames().has(name)) {
            console.error(chalk.red(`"${name}" is reserved (collides with an agent CLI or the agents binary).`));
            process.exit(1);
        }
        const target = shimPath(name);
        if (fs.existsSync(target) && !isAliasShim(target)) {
            console.error(chalk.red(`Refusing to overwrite ${target} -- not an agents-cli alias shim.`));
            process.exit(1);
        }
        fs.mkdirSync(getShimsDir(), { recursive: true });
        fs.writeFileSync(target, generateAliasShim(name, expanded), 'utf-8');
        fs.chmodSync(target, 0o755);
        const map = readAliases();
        map[name] = expanded;
        writeAliases(map);
        console.log(`${chalk.green('Created')} alias ${chalk.bold(name)} -> ${chalk.dim(`agents ${expanded}`)}`);
    });
    cmd
        .command('remove <name>')
        .alias('rm')
        .description('Delete an alias shim')
        .action((name) => {
        const map = readAliases();
        const target = shimPath(name);
        if (!(name in map) && !fs.existsSync(target)) {
            console.error(chalk.red(`No alias named "${name}".`));
            process.exit(1);
        }
        if (fs.existsSync(target)) {
            if (!isAliasShim(target)) {
                console.error(chalk.red(`Refusing to delete ${target} -- not an agents-cli alias shim.`));
                process.exit(1);
            }
            fs.unlinkSync(target);
        }
        delete map[name];
        writeAliases(map);
        console.log(`${chalk.yellow('Removed')} alias ${chalk.bold(name)}`);
    });
    cmd
        .command('list')
        .alias('ls')
        .description('Show installed aliases')
        .action(() => {
        const map = readAliases();
        const entries = Object.entries(map);
        if (entries.length === 0) {
            console.log(chalk.gray('No aliases. Try: agents setup alias add teams'));
            return;
        }
        const width = entries.reduce((max, [n]) => Math.max(max, n.length), 0);
        for (const [name, expansion] of entries) {
            console.log(`  ${chalk.bold(name.padEnd(width))}  ${chalk.dim('->')} agents ${expansion}`);
        }
    });
}
