import { PigApiClient, PigApiError } from './api';

const VERSION = '0.1.0';

const HELP = `Usage: pig [--json] [--api-url URL] [--api-key KEY] <command>

Read commands:
  me
  accounts [list] [--side SIDE] [--query TEXT]
  accounts get <account-id>
  deals demand | supply
  commitments [list]
  allocations [list]
  capacity availability [--gpu-type TYPE]
  capacity match --gpu-count N [filters]
  capacity search [--gpu-type TYPE] [--min-gpu-count N] [--max-price-cents N]
  capacity margin
  capacity idle [--threshold FRACTION] [--within-days N]

Write commands (requires an API key with write scope and the relevant role):
  commitments create --account-id ID --name NAME --gpu-type TYPE --gpu-count N
    --starts-at ISO --ends-at ISO --total-gpu-hours N --cost-per-gpu-hour-cents N
  commitments update <commitment-id> [fields]
  allocations create --commitment-id ID --demand-deal-id ID --gpu-hours N
    --price-per-gpu-hour-cents N --starts-at ISO --ends-at ISO --status STATUS
  allocations hold --commitment-id ID --demand-deal-id ID --gpu-hours N
    --starts-at ISO --ends-at ISO --hold-expires-at ISO
  allocations release <allocation-id> [--reason TEXT]

Configuration:
  PIG_API_URL and PIG_API_KEY, overridden by --api-url and --api-key.
  --json writes only JSON to stdout; errors are JSON on stderr with a non-zero exit.`;

type Writer = (value: string) => void;

export interface RunCliOptions {
  env?: NodeJS.ProcessEnv;
  fetchImpl?: typeof fetch;
  stdout?: Writer;
  stderr?: Writer;
}

class CliUsageError extends Error {
  readonly code = 'invalid_usage';
}

interface GlobalOptions {
  json: boolean;
  help: boolean;
  version: boolean;
  apiUrl?: string;
  apiKey?: string;
  tokens: string[];
}

type OptionKind = 'flag' | 'value' | 'repeat';
type OptionSpec = Readonly<Record<string, OptionKind>>;
type ParsedValue = boolean | string | string[];

interface ParsedOptions {
  options: Map<string, ParsedValue>;
  positionals: string[];
}

interface CommandResult {
  kind: string;
  data: unknown;
}

function usage(message: string): never {
  throw new CliUsageError(message);
}

function globalValue(args: readonly string[], index: number, name: string): string {
  const value = args[index + 1];
  if (!value || value.startsWith('--')) usage(`${name} requires a value.`);
  return value;
}

function parseGlobals(args: readonly string[]): GlobalOptions {
  const result: GlobalOptions = {
    json: false,
    help: false,
    version: false,
    tokens: [],
  };

  for (let index = 0; index < args.length; index += 1) {
    const token = args[index];
    if (token === '--json') {
      result.json = true;
    } else if (token === '--help' || token === '-h') {
      result.help = true;
    } else if (token === '--version') {
      result.version = true;
    } else if (token === '--api-url') {
      result.apiUrl = globalValue(args, index, '--api-url');
      index += 1;
    } else if (token?.startsWith('--api-url=')) {
      result.apiUrl = token.slice('--api-url='.length);
      if (!result.apiUrl) usage('--api-url requires a value.');
    } else if (token === '--api-key') {
      result.apiKey = globalValue(args, index, '--api-key');
      index += 1;
    } else if (token?.startsWith('--api-key=')) {
      result.apiKey = token.slice('--api-key='.length);
      if (!result.apiKey) usage('--api-key requires a value.');
    } else if (token !== undefined) {
      result.tokens.push(token);
    }
  }

  return result;
}

function candidateSecrets(args: readonly string[], env: NodeJS.ProcessEnv): string[] {
  const values = new Set<string>();
  if (env.PIG_API_KEY) values.add(env.PIG_API_KEY);
  for (let index = 0; index < args.length; index += 1) {
    const token = args[index];
    if (token === '--api-key' && args[index + 1]) values.add(args[index + 1]!);
    if (token?.startsWith('--api-key=')) values.add(token.slice('--api-key='.length));
  }
  return [...values].filter(Boolean);
}

function redact(value: string, secrets: readonly string[]): string {
  return secrets.reduce(
    (redacted, secret) => redacted.split(secret).join('[REDACTED]'),
    value,
  );
}

function parseOptions(args: readonly string[], spec: OptionSpec): ParsedOptions {
  const options = new Map<string, ParsedValue>();
  const positionals: string[] = [];

  for (let index = 0; index < args.length; index += 1) {
    const token = args[index];
    if (!token?.startsWith('--')) {
      if (token !== undefined) positionals.push(token);
      continue;
    }

    const equalsAt = token.indexOf('=');
    const name = token.slice(2, equalsAt === -1 ? undefined : equalsAt);
    const inline = equalsAt === -1 ? undefined : token.slice(equalsAt + 1);
    const kind = spec[name];
    if (!kind) usage(`Unknown option --${name}.`);

    if (kind === 'flag') {
      if (inline !== undefined) usage(`--${name} does not take a value.`);
      options.set(name, true);
      continue;
    }

    const value = inline ?? args[index + 1];
    if (value === undefined || (inline === undefined && value.startsWith('--'))) {
      usage(`--${name} requires a value.`);
    }
    if (inline === undefined) index += 1;

    if (kind === 'repeat') {
      const existing = options.get(name);
      options.set(name, [...(Array.isArray(existing) ? existing : []), value]);
    } else {
      if (options.has(name)) usage(`--${name} may only be provided once.`);
      options.set(name, value);
    }
  }

  return { options, positionals };
}

function expectPositionals(
  positionals: readonly string[],
  minimum: number,
  maximum: number,
  commandUsage: string,
): void {
  if (positionals.length < minimum || positionals.length > maximum) {
    usage(`Usage: ${commandUsage}`);
  }
}

function option(options: Map<string, ParsedValue>, name: string): string | undefined {
  const value = options.get(name);
  return typeof value === 'string' ? value : undefined;
}

function requiredOption(options: Map<string, ParsedValue>, name: string): string {
  const value = option(options, name);
  if (value === undefined || value.length === 0) usage(`--${name} is required.`);
  return value;
}

function repeated(options: Map<string, ParsedValue>, name: string): string[] | undefined {
  const value = options.get(name);
  return Array.isArray(value) ? value : undefined;
}

interface NumberRules {
  integer?: boolean;
  minimum?: number;
  maximum?: number;
  nullable?: boolean;
}

function numeric(
  options: Map<string, ParsedValue>,
  name: string,
  rules: NumberRules = {},
): number | null | undefined {
  const raw = option(options, name);
  if (raw === undefined) return undefined;
  if (rules.nullable && raw === 'null') return null;
  const value = Number(raw);
  if (!Number.isFinite(value)) usage(`--${name} must be a number.`);
  if (rules.integer && !Number.isInteger(value)) usage(`--${name} must be an integer.`);
  if (rules.minimum !== undefined && value < rules.minimum) {
    usage(`--${name} must be at least ${rules.minimum}.`);
  }
  if (rules.maximum !== undefined && value > rules.maximum) {
    usage(`--${name} must be at most ${rules.maximum}.`);
  }
  return value;
}

function requiredNumeric(
  options: Map<string, ParsedValue>,
  name: string,
  rules: NumberRules = {},
): number {
  const value = numeric(options, name, rules);
  if (typeof value !== 'number') usage(`--${name} is required.`);
  return value;
}

function booleanValue(
  options: Map<string, ParsedValue>,
  name: string,
): boolean | undefined {
  const raw = option(options, name);
  if (raw === undefined) return undefined;
  if (raw === 'true') return true;
  if (raw === 'false') return false;
  usage(`--${name} must be true or false.`);
}

function nullableString(
  options: Map<string, ParsedValue>,
  name: string,
): string | null | undefined {
  const value = option(options, name);
  return value === 'null' ? null : value;
}

function setDefined(target: Record<string, unknown>, name: string, value: unknown): void {
  if (value !== undefined) target[name] = value;
}

const ACCOUNT_LIST_OPTIONS: OptionSpec = {
  side: 'value',
  query: 'value',
};

const CAPACITY_MATCH_OPTIONS: OptionSpec = {
  'gpu-type': 'value',
  'gpu-type-alternative': 'repeat',
  'gpu-count': 'value',
  'total-gpu-hours': 'value',
  'fast-fabric': 'flag',
  'min-security-tier': 'value',
  'starts-at': 'value',
  'ends-at': 'value',
  'max-price-cents': 'value',
};

const COMMITMENT_OPTIONS: OptionSpec = {
  'account-id': 'value',
  'site-id': 'value',
  'supply-deal-id': 'value',
  name: 'value',
  'gpu-type': 'value',
  socket: 'value',
  'gpu-count': 'value',
  interconnect: 'value',
  'security-tier': 'value',
  'starts-at': 'value',
  'ends-at': 'value',
  'total-gpu-hours': 'value',
  'cost-per-gpu-hour-cents': 'value',
  currency: 'value',
  'shape-interval': 'repeat',
  'shape-quantity': 'repeat',
  'clear-shape': 'flag',
  'colocate-with': 'repeat',
  'clear-colocate': 'flag',
  'is-contiguous': 'value',
  'minimum-spend-cents': 'value',
  'auto-renew': 'value',
  'notice-days': 'value',
  'take-or-pay-floor-pct': 'value',
  'prepaid-pct': 'value',
  'prepaid-amount-cents': 'value',
  'useful-life-years': 'value',
  'salvage-value-pct': 'value',
  'depreciation-start-at': 'value',
  'cost-of-capital-bps': 'value',
  'financing-instrument': 'value',
  'oversubscription-pct': 'value',
  notes: 'value',
};

const COMMITMENT_UPDATE_OPTIONS: OptionSpec = {
  ...COMMITMENT_OPTIONS,
  'terminated-at': 'value',
};

const ALLOCATION_BASE_OPTIONS: OptionSpec = {
  'commitment-id': 'value',
  'demand-deal-id': 'value',
  'gpu-hours': 'value',
  'price-per-gpu-hour-cents': 'value',
  currency: 'value',
  'starts-at': 'value',
  'ends-at': 'value',
  guarantee: 'value',
  priority: 'value',
  'compliance-decision-id': 'value',
  notes: 'value',
};

function buildCommitmentBody(
  options: Map<string, ParsedValue>,
  update: boolean,
): Record<string, unknown> {
  const body: Record<string, unknown> = {};

  const requiredText = (name: string) =>
    update ? option(options, name) : requiredOption(options, name);
  const requiredNumber = (name: string, rules: NumberRules) =>
    update ? numeric(options, name, rules) : requiredNumeric(options, name, rules);

  setDefined(body, 'accountId', requiredText('account-id'));
  setDefined(body, 'siteId', nullableString(options, 'site-id'));
  setDefined(body, 'supplyDealId', nullableString(options, 'supply-deal-id'));
  setDefined(body, 'name', requiredText('name'));
  setDefined(body, 'gpuType', requiredText('gpu-type'));
  setDefined(body, 'socket', nullableString(options, 'socket'));
  setDefined(body, 'gpuCount', requiredNumber('gpu-count', { integer: true, minimum: 1 }));
  setDefined(body, 'interconnectType', option(options, 'interconnect'));
  setDefined(body, 'securityTier', option(options, 'security-tier'));
  setDefined(body, 'startsAt', requiredText('starts-at'));
  setDefined(body, 'endsAt', requiredText('ends-at'));
  setDefined(body, 'totalGpuHours', requiredNumber('total-gpu-hours', { minimum: 0.01 }));
  setDefined(
    body,
    'costPerGpuHourCents',
    requiredNumber('cost-per-gpu-hour-cents', { integer: true, minimum: 0 }),
  );
  setDefined(body, 'currency', option(options, 'currency'));
  setDefined(body, 'isContiguous', booleanValue(options, 'is-contiguous'));
  setDefined(
    body,
    'minimumSpendCents',
    numeric(options, 'minimum-spend-cents', { integer: true, minimum: 0, nullable: true }),
  );
  setDefined(body, 'isAutoRenew', booleanValue(options, 'auto-renew'));
  setDefined(
    body,
    'noticeDays',
    numeric(options, 'notice-days', { integer: true, minimum: 0, nullable: true }),
  );
  setDefined(
    body,
    'takeOrPayFloorPct',
    numeric(options, 'take-or-pay-floor-pct', { minimum: 0, maximum: 100, nullable: true }),
  );
  setDefined(
    body,
    'prepaidPct',
    numeric(options, 'prepaid-pct', { minimum: 0, maximum: 100, nullable: true }),
  );
  setDefined(
    body,
    'prepaidAmountCents',
    numeric(options, 'prepaid-amount-cents', { integer: true, minimum: 0, nullable: true }),
  );
  setDefined(
    body,
    'usefulLifeYears',
    numeric(options, 'useful-life-years', { minimum: 0, maximum: 100, nullable: true }),
  );
  setDefined(
    body,
    'salvageValuePct',
    numeric(options, 'salvage-value-pct', { minimum: 0, maximum: 100, nullable: true }),
  );
  setDefined(body, 'depreciationStartAt', nullableString(options, 'depreciation-start-at'));
  setDefined(
    body,
    'costOfCapitalBps',
    numeric(options, 'cost-of-capital-bps', { integer: true, minimum: 0, nullable: true }),
  );
  setDefined(body, 'financingInstrument', nullableString(options, 'financing-instrument'));
  setDefined(
    body,
    'oversubscriptionPct',
    numeric(options, 'oversubscription-pct', { minimum: 0, maximum: 1_000 }),
  );
  setDefined(body, 'notes', nullableString(options, 'notes'));

  if (update) setDefined(body, 'terminatedAt', nullableString(options, 'terminated-at'));

  const intervals = repeated(options, 'shape-interval');
  const quantityValues = repeated(options, 'shape-quantity');
  const clearShape = options.get('clear-shape') === true;
  if (clearShape && (intervals || quantityValues)) {
    usage('--clear-shape cannot be combined with shape intervals or quantities.');
  }
  if (clearShape) body.shape = null;
  if (intervals || quantityValues) {
    if (!intervals || !quantityValues) {
      usage('--shape-interval and --shape-quantity must be provided together.');
    }
    const quantities = quantityValues.map((raw) => {
      const value = Number(raw);
      if (!Number.isInteger(value) || value < 0) {
        usage('--shape-quantity must contain non-negative integers.');
      }
      return value;
    });
    body.shape = { intervals, quantities };
  }

  const colocateWith = repeated(options, 'colocate-with');
  const clearColocate = options.get('clear-colocate') === true;
  if (clearColocate && colocateWith) {
    usage('--clear-colocate cannot be combined with --colocate-with.');
  }
  if (clearColocate) body.colocateWith = [];
  if (colocateWith) body.colocateWith = colocateWith;

  if (update && Object.keys(body).length === 0) {
    usage('At least one commitment field is required for update.');
  }
  return body;
}

function buildAllocationBase(
  options: Map<string, ParsedValue>,
  priceRequired: boolean,
): Record<string, unknown> {
  const body: Record<string, unknown> = {
    capacityCommitmentId: requiredOption(options, 'commitment-id'),
    demandDealId: requiredOption(options, 'demand-deal-id'),
    gpuHours: requiredNumeric(options, 'gpu-hours', { minimum: 0.01 }),
    startsAt: requiredOption(options, 'starts-at'),
    endsAt: requiredOption(options, 'ends-at'),
  };
  const price = priceRequired
    ? requiredNumeric(options, 'price-per-gpu-hour-cents', { integer: true, minimum: 0 })
    : numeric(options, 'price-per-gpu-hour-cents', { integer: true, minimum: 0 });
  setDefined(body, 'pricePerGpuHourCents', price);
  setDefined(body, 'currency', option(options, 'currency'));
  setDefined(body, 'guaranteeType', option(options, 'guarantee'));
  setDefined(body, 'priority', numeric(options, 'priority', { integer: true, minimum: 0 }));
  setDefined(body, 'complianceDecisionId', nullableString(options, 'compliance-decision-id'));
  setDefined(body, 'notes', nullableString(options, 'notes'));
  return body;
}

async function accountsCommand(
  api: PigApiClient,
  tokens: readonly string[],
): Promise<CommandResult> {
  if (tokens[0] === 'get') {
    const parsed = parseOptions(tokens.slice(1), {});
    expectPositionals(parsed.positionals, 1, 1, 'pig accounts get <account-id>');
    return {
      kind: 'account',
      data: await api.request(`/api/accounts/${encodeURIComponent(parsed.positionals[0]!)}`),
    };
  }

  const listTokens = tokens[0] === 'list' ? tokens.slice(1) : tokens;
  if (listTokens[0] && !listTokens[0]!.startsWith('--')) {
    usage('Usage: pig accounts [list] [--side SIDE] [--query TEXT]');
  }
  const parsed = parseOptions(listTokens, ACCOUNT_LIST_OPTIONS);
  expectPositionals(parsed.positionals, 0, 0, 'pig accounts [list] [options]');
  return {
    kind: 'accounts',
    data: await api.request('/api/accounts', {
      query: { side: option(parsed.options, 'side'), q: option(parsed.options, 'query') },
    }),
  };
}

async function dealsCommand(
  api: PigApiClient,
  tokens: readonly string[],
): Promise<CommandResult> {
  const parsed = parseOptions(tokens, {});
  expectPositionals(parsed.positionals, 1, 1, 'pig deals demand|supply');
  const side = parsed.positionals[0];
  if (side !== 'demand' && side !== 'supply') usage('Deal side must be demand or supply.');
  return { kind: `${side}-deals`, data: await api.request(`/api/deals/${side}`) };
}

async function commitmentsCommand(
  api: PigApiClient,
  tokens: readonly string[],
): Promise<CommandResult> {
  const action = tokens[0];
  if (!action || action === 'list') {
    const parsed = parseOptions(action ? tokens.slice(1) : tokens, {});
    expectPositionals(parsed.positionals, 0, 0, 'pig commitments [list]');
    return { kind: 'commitments', data: await api.request('/api/commitments') };
  }
  if (action === 'create') {
    const parsed = parseOptions(tokens.slice(1), COMMITMENT_OPTIONS);
    expectPositionals(parsed.positionals, 0, 0, 'pig commitments create [fields]');
    return {
      kind: 'commitment-created',
      data: await api.request('/api/commitments', {
        method: 'POST',
        body: buildCommitmentBody(parsed.options, false),
      }),
    };
  }
  if (action === 'update') {
    const parsed = parseOptions(tokens.slice(1), COMMITMENT_UPDATE_OPTIONS);
    expectPositionals(parsed.positionals, 1, 1, 'pig commitments update <id> [fields]');
    return {
      kind: 'commitment-updated',
      data: await api.request(
        `/api/commitments/${encodeURIComponent(parsed.positionals[0]!)}`,
        { method: 'PATCH', body: buildCommitmentBody(parsed.options, true) },
      ),
    };
  }
  usage('Usage: pig commitments list|create|update');
}

async function allocationsCommand(
  api: PigApiClient,
  tokens: readonly string[],
): Promise<CommandResult> {
  const action = tokens[0];
  if (!action || action === 'list') {
    const parsed = parseOptions(action ? tokens.slice(1) : tokens, {});
    expectPositionals(parsed.positionals, 0, 0, 'pig allocations [list]');
    return { kind: 'allocations', data: await api.request('/api/allocations') };
  }
  if (action === 'create') {
    const parsed = parseOptions(tokens.slice(1), {
      ...ALLOCATION_BASE_OPTIONS,
      status: 'value',
    });
    expectPositionals(parsed.positionals, 0, 0, 'pig allocations create [fields]');
    const body = buildAllocationBase(parsed.options, true);
    body.status = requiredOption(parsed.options, 'status');
    return {
      kind: 'allocation-created',
      data: await api.request('/api/allocations', { method: 'POST', body }),
    };
  }
  if (action === 'hold') {
    const parsed = parseOptions(tokens.slice(1), {
      ...ALLOCATION_BASE_OPTIONS,
      'hold-expires-at': 'value',
      'hold-opportunity-cost-cents': 'value',
    });
    expectPositionals(parsed.positionals, 0, 0, 'pig allocations hold [fields]');
    const body = buildAllocationBase(parsed.options, false);
    body.holdExpiresAt = requiredOption(parsed.options, 'hold-expires-at');
    setDefined(
      body,
      'holdOpportunityCostCents',
      numeric(parsed.options, 'hold-opportunity-cost-cents', {
        integer: true,
        minimum: 0,
        nullable: true,
      }),
    );
    return {
      kind: 'allocation-held',
      data: await api.request('/api/allocations/holds', { method: 'POST', body }),
    };
  }
  if (action === 'release') {
    const parsed = parseOptions(tokens.slice(1), { reason: 'value' });
    expectPositionals(parsed.positionals, 1, 1, 'pig allocations release <id> [--reason TEXT]');
    const body: Record<string, unknown> = {};
    setDefined(body, 'reason', option(parsed.options, 'reason'));
    return {
      kind: 'allocation-released',
      data: await api.request(
        `/api/allocations/${encodeURIComponent(parsed.positionals[0]!)}/release`,
        { method: 'POST', body },
      ),
    };
  }
  usage('Usage: pig allocations list|create|hold|release');
}

async function capacityCommand(
  api: PigApiClient,
  tokens: readonly string[],
): Promise<CommandResult> {
  const action = tokens[0];
  if (action === 'availability') {
    const parsed = parseOptions(tokens.slice(1), { 'gpu-type': 'value' });
    expectPositionals(parsed.positionals, 0, 0, 'pig capacity availability [options]');
    return {
      kind: 'capacity-availability',
      data: await api.request('/api/capacity/availability', {
        query: { gpuType: option(parsed.options, 'gpu-type') },
      }),
    };
  }
  if (action === 'match') {
    const parsed = parseOptions(tokens.slice(1), CAPACITY_MATCH_OPTIONS);
    expectPositionals(parsed.positionals, 0, 0, 'pig capacity match [options]');
    const body: Record<string, unknown> = {
      gpuCount: requiredNumeric(parsed.options, 'gpu-count', { integer: true, minimum: 1 }),
    };
    setDefined(body, 'gpuType', option(parsed.options, 'gpu-type'));
    setDefined(body, 'gpuTypeAlternatives', repeated(parsed.options, 'gpu-type-alternative'));
    setDefined(body, 'totalGpuHours', numeric(parsed.options, 'total-gpu-hours', { minimum: 0.01 }));
    if (parsed.options.get('fast-fabric') === true) body.requiresHighSpeedInterconnect = true;
    setDefined(body, 'minSecurityTier', option(parsed.options, 'min-security-tier'));
    setDefined(body, 'startsAt', option(parsed.options, 'starts-at'));
    setDefined(body, 'endsAt', option(parsed.options, 'ends-at'));
    setDefined(
      body,
      'maxPricePerGpuHourCents',
      numeric(parsed.options, 'max-price-cents', { integer: true, minimum: 1 }),
    );
    return {
      kind: 'capacity-matches',
      data: await api.request('/api/capacity/match', { method: 'POST', body }),
    };
  }
  if (action === 'search') {
    const parsed = parseOptions(tokens.slice(1), {
      'gpu-type': 'value',
      'min-gpu-count': 'value',
      'max-price-cents': 'value',
      'fast-fabric': 'flag',
      limit: 'value',
    });
    expectPositionals(parsed.positionals, 0, 0, 'pig capacity search [options]');
    return {
      kind: 'inventory',
      data: await api.request('/api/inventory', {
        query: {
          gpuType: option(parsed.options, 'gpu-type'),
          minGpuCount:
            numeric(parsed.options, 'min-gpu-count', { integer: true, minimum: 1 }) ?? undefined,
          maxPriceCents:
            numeric(parsed.options, 'max-price-cents', { integer: true, minimum: 1 }) ?? undefined,
          fastFabric: parsed.options.get('fast-fabric') === true ? true : undefined,
          limit:
            numeric(parsed.options, 'limit', { integer: true, minimum: 1, maximum: 100 }) ??
            undefined,
        },
      }),
    };
  }
  if (action === 'margin') {
    const parsed = parseOptions(tokens.slice(1), {});
    expectPositionals(parsed.positionals, 0, 0, 'pig capacity margin');
    return { kind: 'margin', data: await api.request('/api/capacity/margin') };
  }
  if (action === 'idle') {
    const parsed = parseOptions(tokens.slice(1), {
      threshold: 'value',
      'within-days': 'value',
    });
    expectPositionals(parsed.positionals, 0, 0, 'pig capacity idle [options]');
    return {
      kind: 'idle',
      data: await api.request('/api/capacity/idle', {
        query: {
          threshold:
            numeric(parsed.options, 'threshold', { minimum: 0, maximum: 1 }) ?? undefined,
          withinDays:
            numeric(parsed.options, 'within-days', { integer: true, minimum: 1 }) ?? undefined,
        },
      }),
    };
  }
  usage('Usage: pig capacity availability|match|search|margin|idle');
}

async function dispatch(api: PigApiClient, tokens: readonly string[]): Promise<CommandResult> {
  const command = tokens[0];
  const rest = tokens.slice(1);
  if (command === 'me') {
    const parsed = parseOptions(rest, {});
    expectPositionals(parsed.positionals, 0, 0, 'pig me');
    return { kind: 'me', data: await api.request('/api/me') };
  }
  if (command === 'accounts') return accountsCommand(api, rest);
  if (command === 'deals') return dealsCommand(api, rest);
  if (command === 'commitments') return commitmentsCommand(api, rest);
  if (command === 'allocations') return allocationsCommand(api, rest);
  if (command === 'capacity') return capacityCommand(api, rest);
  usage(`Unknown command ${JSON.stringify(command)}. Run pig --help for usage.`);
}

function asRecord(value: unknown): Record<string, unknown> | null {
  return value !== null && typeof value === 'object' && !Array.isArray(value)
    ? (value as Record<string, unknown>)
    : null;
}

function summaryLine(value: unknown): string {
  const row = asRecord(value);
  if (!row) return String(value);
  const nested = asRecord(row.commitment) ?? asRecord(row.deal) ?? row;
  const name = typeof nested.name === 'string' ? nested.name : undefined;
  const id = typeof nested.id === 'string' ? nested.id : undefined;
  const gpuType = typeof nested.gpuType === 'string' ? nested.gpuType : undefined;
  const gpuCount = typeof nested.gpuCount === 'number' ? nested.gpuCount : undefined;
  const stage = typeof nested.stage === 'string' ? nested.stage : undefined;
  const status = typeof nested.status === 'string' ? nested.status : undefined;
  const accountName = typeof row.accountName === 'string' ? row.accountName : undefined;
  return [
    name ?? accountName ?? id ?? 'record',
    gpuType,
    gpuCount ? `${gpuCount} GPUs` : undefined,
    stage ?? status,
    id,
  ]
    .filter(Boolean)
    .join(' | ');
}

function humanOutput(result: CommandResult): string {
  const data = result.data;
  if (result.kind === 'me') {
    const me = asRecord(data);
    if (me) {
      const teams = Array.isArray(me.teams)
        ? me.teams.map((team) => {
            const value = asRecord(team);
            return value ? `${String(value.team)} (${String(value.role)})` : String(team);
          })
        : [];
      return [
        `${String(me.name ?? 'Unknown')} <${String(me.email ?? 'no email')}>`,
        teams.length ? `Teams: ${teams.join(', ')}` : 'Teams: none',
        me.isPlatformAdmin === true ? 'Platform admin.' : undefined,
      ]
        .filter(Boolean)
        .join('\n');
    }
  }

  if (Array.isArray(data)) {
    if (data.length === 0) return 'No results.';
    return `${data.length} result(s)\n${data.map((row) => `- ${summaryLine(row)}`).join('\n')}`;
  }

  if (result.kind.endsWith('-deals')) {
    const value = asRecord(data);
    if (value && Array.isArray(value.deals)) {
      return `${value.deals.length} deal(s)\n${value.deals
        .map((row) => `- ${summaryLine(row)}`)
        .join('\n')}`;
    }
  }

  if (result.kind === 'margin') {
    const value = asRecord(data);
    const totals = asRecord(value?.totals);
    if (totals) {
      const marginPct =
        typeof totals.grossMarginPct === 'number'
          ? `${(totals.grossMarginPct * 100).toFixed(1)}%`
          : 'n/a';
      return [
        `Revenue: ${String(totals.revenueCents ?? 0)} cents`,
        `Cost: ${String(totals.costCents ?? 0)} cents`,
        `Gross margin: ${String(totals.grossMarginCents ?? 0)} cents (${marginPct})`,
        `Idle: ${String(totals.idleGpuHours ?? 0)} GPU-hours`,
      ].join('\n');
    }
  }

  if (
    result.kind.endsWith('-created') ||
    result.kind.endsWith('-updated') ||
    result.kind.endsWith('-held') ||
    result.kind.endsWith('-released')
  ) {
    return `${result.kind.replaceAll('-', ' ')}: ${summaryLine(data)}`;
  }

  return JSON.stringify(data, null, 2);
}

function errorShape(error: unknown): { error: Record<string, unknown>; exitCode: number } {
  if (error instanceof PigApiError) {
    return {
      error: {
        code: error.code,
        message: error.message,
        ...(error.status !== undefined ? { status: error.status } : {}),
        ...(error.details !== undefined ? { details: error.details } : {}),
      },
      exitCode: 1,
    };
  }
  if (error instanceof CliUsageError) {
    return { error: { code: error.code, message: error.message }, exitCode: 2 };
  }
  return {
    error: {
      code: 'internal_error',
      message: error instanceof Error ? error.message : 'Unexpected CLI failure.',
    },
    exitCode: 1,
  };
}

function validateApiUrl(value: string): string {
  let url: URL;
  try {
    url = new URL(value);
  } catch {
    usage('PIG_API_URL/--api-url must be a valid HTTP(S) URL.');
  }
  if (url.protocol !== 'http:' && url.protocol !== 'https:') {
    usage('PIG_API_URL/--api-url must use HTTP or HTTPS.');
  }
  return value;
}

export async function runCli(args: readonly string[], options: RunCliOptions = {}): Promise<number> {
  const env = options.env ?? process.env;
  const stdout = options.stdout ?? ((value: string) => process.stdout.write(value));
  const stderr = options.stderr ?? ((value: string) => process.stderr.write(value));
  const secrets = candidateSecrets(args, env);
  const jsonRequested = args.includes('--json');

  try {
    const global = parseGlobals(args);
    if (global.help || global.tokens.length === 0) {
      stdout(global.json ? `${JSON.stringify({ usage: HELP })}\n` : `${HELP}\n`);
      return 0;
    }
    if (global.version) {
      stdout(global.json ? `${JSON.stringify({ version: VERSION })}\n` : `${VERSION}\n`);
      return 0;
    }

    const apiUrl = global.apiUrl ?? env.PIG_API_URL;
    const apiKey = global.apiKey ?? env.PIG_API_KEY;
    if (!apiUrl) usage('Set PIG_API_URL or pass --api-url.');
    if (!apiKey) usage('Set PIG_API_KEY or pass --api-key.');

    const api = new PigApiClient({
      baseUrl: validateApiUrl(apiUrl),
      apiKey,
      fetchImpl: options.fetchImpl,
    });
    const result = await dispatch(api, global.tokens);
    const output = global.json ? JSON.stringify(result.data ?? null) : humanOutput(result);
    stdout(`${redact(output, secrets)}\n`);
    return 0;
  } catch (error) {
    const shaped = errorShape(error);
    const output = jsonRequested
      ? JSON.stringify({ error: shaped.error })
      : `Error [${String(shaped.error.code)}]: ${String(shaped.error.message)}`;
    stderr(`${redact(output, secrets)}\n`);
    return shaped.exitCode;
  }
}
