import { Command } from 'commander';
import type { ApiClient } from '../api-client.js';
import { resolveNameOrId } from './shared.js';

export interface FavouritesCommandDeps {
  client: ApiClient;
  log: (...args: string[]) => void;
  getProject: () => string | undefined;
}

interface ToolUsageEntry {
  tool: string;
  server: string | null;
  count: number;
}

interface ProjectFavouriteIndex {
  favouriteIndex?: { enabled?: boolean; tools?: string[]; maxFavourites?: number };
}

function requireProject(deps: FavouritesCommandDeps): string {
  const project = deps.getProject();
  if (!project) {
    deps.log('Error: --project <name> is required for this command.');
    process.exitCode = 1;
    throw new Error('--project required');
  }
  return project;
}

/**
 * `mcpctl favourites` — inspect + derive the curated favourite/ shortlist used
 * by the favourite-index tool presentation. `suggest` ranks tools by real usage
 * so you can pick pins; `list` shows what the proxy will present.
 */
export function createFavouritesCommand(deps: FavouritesCommandDeps): Command {
  const { client, log } = deps;

  const cmd = new Command('favourites')
    .description('Inspect / derive a project\'s favourite-index tool shortlist (requires --project)');

  cmd.command('suggest')
    .description('Rank tools by usage to pick favourite/ pins')
    .option('--top <n>', 'How many to show (default 20)', '20')
    .option('--window <days>', 'Look-back window in days (default 30)', '30')
    .action(async (opts: { top: string; window: string }) => {
      const projectName = requireProject(deps);
      const top = Number(opts.top) > 0 ? Number(opts.top) : 20;
      const windowDays = Number(opts.window) > 0 ? Number(opts.window) : 30;
      const res = await client.get<{ tools: ToolUsageEntry[] }>(
        `/api/v1/audit/tool-usage?projectName=${encodeURIComponent(projectName)}&window=${windowDays}&limit=${top}`,
      );
      const tools = res.tools ?? [];

      // Mark which candidates are already pinned.
      const project = await client.get<ProjectFavouriteIndex>(
        `/api/v1/projects/${await resolveNameOrId(client, 'projects', projectName)}`,
      );
      const pinned = new Set(project.favouriteIndex?.tools ?? []);

      if (tools.length === 0) {
        log(`No tool-call usage recorded for project '${projectName}' in the last ${windowDays}d.`);
        return;
      }
      log(`Top ${tools.length} tools for '${projectName}' (last ${windowDays}d):`);
      log('');
      log(`  ${'#'.padStart(3)}  ${'CALLS'.padStart(6)}  ${'PIN'.padEnd(3)}  TOOL`);
      log(`  ${'-'.repeat(3)}  ${'-'.repeat(6)}  ${'-'.repeat(3)}  ${'-'.repeat(30)}`);
      tools.forEach((t, i) => {
        const mark = pinned.has(t.tool) ? '★' : ' ';
        log(`  ${String(i + 1).padStart(3)}  ${String(t.count).padStart(6)}   ${mark}   ${t.tool}`);
      });
      const unpinned = tools.filter((t) => !pinned.has(t.tool) && !t.tool.startsWith('favourite/'));
      if (unpinned.length > 0) {
        log('');
        log('Pin the common ones (★ = already pinned):');
        const flags = unpinned.slice(0, 10).map((t) => `--favourite ${t.tool}`).join(' ');
        log(`  mcpctl create project ${projectName} --force --favourite-index ${flags}`);
      }
    });

  cmd.command('list')
    .description('Show the favourite-index config the proxy will present')
    .action(async () => {
      const projectName = requireProject(deps);
      const project = await client.get<ProjectFavouriteIndex>(
        `/api/v1/projects/${await resolveNameOrId(client, 'projects', projectName)}`,
      );
      const fav = project.favouriteIndex;
      if (!fav || !fav.enabled) {
        log(`favourite-index is DISABLED for project '${projectName}'.`);
        log(`Enable it with: mcpctl create project ${projectName} --force --favourite-index --favourite <server/tool> ...`);
        return;
      }
      const tools = fav.tools ?? [];
      log(`favourite-index ENABLED for '${projectName}'${fav.maxFavourites ? ` (cap ${fav.maxFavourites})` : ''}:`);
      if (tools.length === 0) {
        log('  (no pins — nothing will be promoted to favourite/)');
      } else {
        tools.forEach((t, i) => log(`  ${String(i + 1).padStart(3)}  ${t}`));
      }
    });

  return cmd;
}
