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

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

export function createDeleteCommand(deps: DeleteCommandDeps): Command {
  const { client, log } = deps;

  return new Command('delete')
    .description('Delete a resource (server, instance, secret, project, user, group, rbac, personality)')
    .argument('<resource>', 'resource type')
    .argument('<id>', 'resource ID or name')
    .option('-p, --project <name>', 'Project name (for serverattachment)')
    .option('--agent <name>', 'Agent name (for personality delete-by-name)')
    .action(async (resourceArg: string, idOrName: string, opts: { project?: string; agent?: string }) => {
      const resource = resolveResource(resourceArg);

      // Chat threads: project-scoped, deleted by id. Owner can delete their own;
      // admins with delete:projects can delete anyone's (enforced server-side).
      if (resource === 'threads') {
        if (!opts.project) {
          throw new Error('--project is required. Usage: mcpctl delete thread <id> --project <name>');
        }
        await client.delete(`/api/v1/projects/${encodeURIComponent(opts.project)}/threads/${encodeURIComponent(idOrName)}`);
        log(`thread '${idOrName}' deleted from project '${opts.project}'.`);
        return;
      }

      // Serverattachments: delete serverattachment <server> --project <project>
      if (resource === 'serverattachments') {
        if (!opts.project) {
          throw new Error('--project is required. Usage: mcpctl delete serverattachment <server> --project <name>');
        }
        const projectId = await resolveNameOrId(client, 'projects', opts.project);
        await client.delete(`/api/v1/projects/${projectId}/servers/${idOrName}`);
        log(`server '${idOrName}' detached from project '${opts.project}'`);
        return;
      }

      // Personalities: names are unique per-agent, so by-name delete requires --agent
      // (or pass a CUID directly).
      if (resource === 'personalities') {
        let personalityId: string;
        if (/^c[a-z0-9]{24}/.test(idOrName)) {
          personalityId = idOrName;
        } else {
          if (!opts.agent) {
            throw new Error('--agent is required to delete a personality by name (or pass the id).');
          }
          const items = await client.get<Array<{ id: string; name: string }>>(
            `/api/v1/agents/${encodeURIComponent(opts.agent)}/personalities`,
          );
          const match = items.find((i) => i.name === idOrName);
          if (!match) throw new Error(`personality '${idOrName}' not found on agent '${opts.agent}'`);
          personalityId = match.id;
        }
        await client.delete(`/api/v1/personalities/${personalityId}`);
        log(`personality '${idOrName}' deleted.`);
        return;
      }

      // Mcptokens: names are scoped to a project, so require --project unless the caller passes a CUID
      if (resource === 'mcptokens') {
        let tokenId: string;
        if (/^c[a-z0-9]{24}/.test(idOrName)) {
          tokenId = idOrName;
        } else {
          if (!opts.project) {
            throw new Error('--project is required to delete an mcptoken by name (or pass the id).');
          }
          const items = await client.get<Array<{ id: string; name: string }>>(
            `/api/v1/mcptokens?projectName=${encodeURIComponent(opts.project)}`,
          );
          const match = items.find((i) => i.name === idOrName);
          if (!match) throw new Error(`mcptoken '${idOrName}' not found in project '${opts.project}'`);
          tokenId = match.id;
        }
        await client.delete(`/api/v1/mcptokens/${tokenId}`);
        log(`mcptoken '${idOrName}' deleted.`);
        return;
      }

      // Resolve name → ID for any resource type
      let id: string;
      try {
        id = await resolveNameOrId(client, resource, idOrName);
      } catch {
        id = idOrName; // Fall through with original
      }

      await client.delete(`/api/v1/${resource}/${id}`);

      const singular = resource.replace(/s$/, '');
      log(`${singular} '${idOrName}' deleted.`);
    });
}
