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

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

/**
 * Parse "key=value" pairs into a partial update object.
 * Supports: key=value, key=null (sets null), key=123 (number if parseable).
 */
function parsePatches(pairs: string[]): Record<string, unknown> {
  const result: Record<string, unknown> = {};
  for (const pair of pairs) {
    const eqIdx = pair.indexOf('=');
    if (eqIdx === -1) {
      throw new Error(`Invalid patch format '${pair}'. Expected key=value`);
    }
    const key = pair.slice(0, eqIdx);
    const raw = pair.slice(eqIdx + 1);

    if (raw === 'null') {
      result[key] = null;
    } else if (raw === 'true') {
      result[key] = true;
    } else if (raw === 'false') {
      result[key] = false;
    } else if (/^\d+$/.test(raw)) {
      result[key] = parseInt(raw, 10);
    } else {
      result[key] = raw;
    }
  }
  return result;
}

export function createPatchCommand(deps: PatchCommandDeps): Command {
  const { client, log } = deps;

  return new Command('patch')
    .description('Patch a resource field (e.g. mcpctl patch project myproj llmProvider=none)')
    .argument('<resource>', 'resource type (server, project, secret, ...)')
    .argument('<name>', 'resource name or ID')
    .argument('<patches...>', 'key=value pairs to patch')
    .action(async (resourceArg: string, nameOrId: string, patches: string[]) => {
      const resource = resolveResource(resourceArg);
      const id = await resolveNameOrId(client, resource, nameOrId);
      const body = parsePatches(patches);

      await client.put(`/api/v1/${resource}/${id}`, body);
      const fields = Object.entries(body)
        .map(([k, v]) => `${k}=${v === null ? 'null' : String(v)}`)
        .join(', ');
      log(`patched ${resource.replace(/s$/, '')} '${nameOrId}': ${fields}`);
    });
}
