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

export interface LogsCommandDeps {
  client: ApiClient;
  log: (...args: unknown[]) => void;
}

interface InstanceInfo {
  id: string;
  status: string;
  containerId: string | null;
}

/**
 * Resolve a name/ID to an instance ID.
 * Accepts: instance ID, server name, or server ID.
 * For servers with multiple replicas, picks by --instance index or first RUNNING.
 */
async function resolveInstance(
  client: ApiClient,
  nameOrId: string,
  instanceIndex?: number,
): Promise<{ instanceId: string; serverName?: string; replicaInfo?: string }> {
  // Try as instance ID first
  try {
    await client.get(`/api/v1/instances/${nameOrId}`);
    return { instanceId: nameOrId };
  } catch {
    // Not a valid instance ID
  }

  // Try as server name/ID → find its instances
  const servers = await client.get<Array<{ id: string; name: string }>>('/api/v1/servers');
  const server = servers.find((s) => s.name === nameOrId || s.id === nameOrId);
  if (!server) {
    throw new Error(`Instance or server '${nameOrId}' not found`);
  }

  const instances = await client.get<InstanceInfo[]>(`/api/v1/instances?serverId=${server.id}`);
  if (instances.length === 0) {
    throw new Error(`No instances found for server '${server.name}'`);
  }

  // Select by index or pick first running
  let selected: InstanceInfo | undefined;
  if (instanceIndex !== undefined) {
    if (instanceIndex < 0 || instanceIndex >= instances.length) {
      throw new Error(`Instance index ${instanceIndex} out of range (server '${server.name}' has ${instances.length} instance${instances.length > 1 ? 's' : ''})`);
    }
    selected = instances[instanceIndex];
  } else {
    selected = instances.find((i) => i.status === 'RUNNING') ?? instances[0];
  }

  if (!selected) {
    throw new Error(`No instances found for server '${server.name}'`);
  }

  const result: { instanceId: string; serverName?: string; replicaInfo?: string } = {
    instanceId: selected.id,
    serverName: server.name,
  };
  if (instances.length > 1) {
    result.replicaInfo = `instance ${instances.indexOf(selected) + 1}/${instances.length}`;
  }
  return result;
}

export function createLogsCommand(deps: LogsCommandDeps): Command {
  const { client, log } = deps;

  return new Command('logs')
    .description('Get logs from an MCP server instance')
    .argument('<name>', 'Server name, server ID, or instance ID')
    .option('-t, --tail <lines>', 'Number of lines to show')
    .option('-i, --instance <index>', 'Instance/replica index (0-based, for servers with multiple replicas)')
    .action(async (nameOrId: string, opts: { tail?: string; instance?: string }) => {
      const instanceIndex = opts.instance !== undefined ? parseInt(opts.instance, 10) : undefined;
      const { instanceId, serverName, replicaInfo } = await resolveInstance(client, nameOrId, instanceIndex);

      if (replicaInfo) {
        process.stderr.write(`Showing logs for ${serverName} (${replicaInfo})\n`);
      }

      let url = `/api/v1/instances/${instanceId}/logs`;
      if (opts.tail) {
        url += `?tail=${opts.tail}`;
      }
      const logs = await client.get<{ stdout: string; stderr: string }>(url);
      if (logs.stdout) {
        log(logs.stdout);
      }
      if (logs.stderr) {
        process.stderr.write(logs.stderr);
      }
    });
}
