/**
 * v2.3 Phase 4 (design.md §8) — per-provider plaintext diagnostic report.
 *
 * Read-only by default: reports CACHED state (resolved registry def + the
 * available_agents row + the warm snapshot-cache entry) plus a `which`-style
 * PATH check for the launch binary. It does NOT spawn an ACP probe — §8 lists
 * the live initialize probe as optional, and the route defaults to cached state.
 *
 * A template string is the whole formatter (no Paseo diagnostic-utils port).
 */
import type { ResolvedProviderDef } from './provider-config-registry.js';
import type { ProviderSnapshotEntry, ProviderModel } from './provider-types.js';
import { isCommandAvailable } from './command-availability.js';

/** The subset of an `available_agents` row the diagnostic reads. */
export interface DiagnosticAgentRow {
  name: string;
  install_path: string | null;
  supports_acp?: boolean;
  models?: ProviderModel[] | null;
  last_probed_at?: string | Date | null;
}

interface DiagnosticOpts {
  /** Warm snapshot-cache entry (read-only peek) — source of the last probe error. */
  cachedEntry?: ProviderSnapshotEntry;
  /** Injectable PATH check (defaults to the real `which`); stubbed in tests. */
  checkAvailable?: (binary: string) => Promise<boolean>;
}

/** Resolve the binary the dispatcher would launch (for the PATH check + report). */
function resolveBinary(resolved: ResolvedProviderDef, agentRow: DiagnosticAgentRow | undefined): string {
  return resolved.launchCommand?.[0] ?? agentRow?.install_path ?? resolved.id;
}

export async function getProviderDiagnostic(
  resolved: ResolvedProviderDef,
  agentRow: DiagnosticAgentRow | undefined,
  opts: DiagnosticOpts = {},
): Promise<string> {
  const checkAvailable = opts.checkAvailable ?? isCommandAvailable;
  const installed = agentRow?.install_path != null;
  const binary = resolveBinary(resolved, agentRow);
  // boocode is native (no binary to launch) — short-circuit the PATH check.
  const commandAvailable = resolved.transport === 'native' ? true : await checkAvailable(binary);
  const lastProbedAt =
    agentRow?.last_probed_at != null ? new Date(agentRow.last_probed_at).toISOString() : '(never)';
  const modelCount = agentRow?.models?.length ?? 0;
  const launchCommand = resolved.launchCommand
    ? resolved.launchCommand.join(' ')
    : '(built-in default, resolved at dispatch)';
  const lastError = opts.cachedEntry?.error ?? '(none recorded)';

  return [
    `provider: ${resolved.id}`,
    `label: ${resolved.configLabel ?? resolved.label}`,
    `transport: ${resolved.transport}`,
    `enabled: ${resolved.enabled}`,
    `builtin: ${resolved.isBuiltin}`,
    `customAcp: ${resolved.isCustomAcp}`,
    `installed: ${installed}`,
    `install_path: ${agentRow?.install_path ?? '(none)'}`,
    `binary: ${binary}`,
    `command_available: ${commandAvailable}`,
    `launch_command: ${launchCommand}`,
    `supports_acp: ${agentRow?.supports_acp ?? '(unknown)'}`,
    `last_probed_at: ${lastProbedAt}`,
    `models_in_db: ${modelCount}`,
    `last_probe_error: ${lastError}`,
  ].join('\n');
}
