/**
 * useOrchestratorCommands hook
 *
 * Parses chat messages for `/command` prefixes and routes them to the
 * orchestrator proxy API routes instead of the LLM.
 *
 * Supported commands:
 *   /status  — GET /api/orchestrator/health
 *   /agents  — GET /api/orchestrator/agents
 *   /jobs    — GET /api/orchestrator/queue/stats
 *   /queue   — alias for /jobs
 *   /pause   — POST /api/orchestrator/queue/pause
 *   /resume  — POST /api/orchestrator/queue/resume
 *   /help    — Display available commands locally (no API call)
 */

import { useCallback } from "react";
import type { Message } from "@/hooks/useChat";

// ---------------------------------------------------------------------------
// Command definitions
// ---------------------------------------------------------------------------

export interface OrchestratorCommand {
  name: string;
  description: string;
  aliases?: string[];
}

export const ORCHESTRATOR_COMMANDS: OrchestratorCommand[] = [
  { name: "/status", description: "Show orchestrator health and status" },
  { name: "/agents", description: "List all running agents" },
  { name: "/jobs", description: "Show queue statistics", aliases: ["/queue"] },
  { name: "/pause", description: "Pause the job queue" },
  { name: "/resume", description: "Resume the job queue" },
  { name: "/help", description: "Show available commands" },
];

// ---------------------------------------------------------------------------
// API response shapes (loosely typed — orchestrator may vary)
// ---------------------------------------------------------------------------

interface HealthResponse {
  status?: string;
  version?: string;
  uptime?: number;
  ready?: boolean;
  error?: string;
}

interface Agent {
  id?: string;
  sessionKey?: string;
  status?: string;
  type?: string;
  agentStatus?: string;
  startedAt?: string;
  label?: string;
  channel?: string;
}

interface AgentsResponse {
  agents?: Agent[];
  error?: string;
}

interface QueueStats {
  pending?: number;
  active?: number;
  completed?: number;
  failed?: number;
  waiting?: number;
  delayed?: number;
  paused?: boolean;
  error?: string;
}

interface ActionResponse {
  success?: boolean;
  message?: string;
  status?: string;
  error?: string;
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function makeId(): string {
  return `orch-${Date.now().toString()}-${Math.random().toString(36).slice(2, 8)}`;
}

function makeMessage(content: string): Message {
  return {
    id: makeId(),
    role: "assistant",
    content,
    createdAt: new Date().toISOString(),
  };
}

function errorMessage(command: string, detail: string): Message {
  return makeMessage(
    `**Error running \`${command}\`**\n\n${detail}\n\n_Check that the orchestrator is running and the API key is configured._`
  );
}

// ---------------------------------------------------------------------------
// Formatters
// ---------------------------------------------------------------------------

function formatStatus(data: HealthResponse): string {
  if (data.error) {
    return `**Orchestrator Status**\n\nStatus: Not reachable\n\nError: ${data.error}`;
  }

  const statusLabel = data.status ?? (data.ready === true ? "ready" : "unknown");
  const isReady =
    statusLabel === "ready" ||
    statusLabel === "ok" ||
    statusLabel === "healthy" ||
    data.ready === true;
  const badge = isReady ? "Ready" : "Not Ready";

  const lines: string[] = [
    `**Orchestrator Status**\n`,
    `| Field | Value |`,
    `|---|---|`,
    `| Status | **${badge}** |`,
  ];

  if (data.version != null) {
    lines.push(`| Version | \`${data.version}\` |`);
  }

  if (data.uptime != null) {
    const uptimeSec = Math.floor(data.uptime);
    const hours = Math.floor(uptimeSec / 3600);
    const mins = Math.floor((uptimeSec % 3600) / 60);
    const secs = uptimeSec % 60;
    const uptimeStr =
      hours > 0
        ? `${String(hours)}h ${String(mins)}m ${String(secs)}s`
        : `${String(mins)}m ${String(secs)}s`;
    lines.push(`| Uptime | ${uptimeStr} |`);
  }

  return lines.join("\n");
}

function formatAgents(raw: unknown): string {
  let agents: Agent[] = [];

  if (Array.isArray(raw)) {
    agents = raw as Agent[];
  } else if (raw !== null && typeof raw === "object") {
    const obj = raw as AgentsResponse;
    if (obj.error) {
      return `**Agents**\n\nError: ${obj.error}`;
    }
    if (Array.isArray(obj.agents)) {
      agents = obj.agents;
    }
  }

  if (agents.length === 0) {
    return "**Agents**\n\nNo agents currently running.";
  }

  const lines: string[] = [
    `**Agents** (${String(agents.length)} total)\n`,
    `| ID / Key | Status | Type / Channel | Started |`,
    `|---|---|---|---|`,
  ];

  for (const agent of agents) {
    const id = agent.id ?? agent.sessionKey ?? "—";
    const status = agent.agentStatus ?? agent.status ?? "—";
    const type = agent.type ?? agent.channel ?? "—";
    const started = agent.startedAt ? new Date(agent.startedAt).toLocaleString() : "—";
    lines.push(`| \`${id}\` | ${status} | ${type} | ${started} |`);
  }

  return lines.join("\n");
}

function formatQueueStats(data: QueueStats): string {
  if (data.error) {
    return `**Queue Stats**\n\nError: ${data.error}`;
  }

  const lines: string[] = [`**Queue Statistics**\n`, `| Metric | Count |`, `|---|---|`];

  const metrics: [string, number | undefined][] = [
    ["Pending", data.pending ?? data.waiting],
    ["Active", data.active],
    ["Delayed", data.delayed],
    ["Completed", data.completed],
    ["Failed", data.failed],
  ];

  for (const [label, value] of metrics) {
    if (value !== undefined) {
      lines.push(`| ${label} | ${String(value)} |`);
    }
  }

  if (data.paused === true) {
    lines.push("\n_Queue is currently **paused**._");
  }

  return lines.join("\n");
}

function formatAction(command: string, data: ActionResponse): string {
  if (data.error) {
    return `**${command}** failed.\n\nError: ${data.error}`;
  }

  const verb = command === "/pause" ? "paused" : "resumed";
  const msg = data.message ?? data.status ?? `Queue ${verb} successfully.`;
  return `**Queue ${verb}**\n\n${msg}`;
}

function formatHelp(): string {
  const lines: string[] = [
    "**Available Orchestrator Commands**\n",
    "| Command | Description |",
    "|---|---|",
  ];

  for (const cmd of ORCHESTRATOR_COMMANDS) {
    const name = cmd.aliases ? `${cmd.name} (${cmd.aliases.join(", ")})` : cmd.name;
    lines.push(`| \`${name}\` | ${cmd.description} |`);
  }

  lines.push("\n_Commands starting with `/` are routed to the orchestrator instead of the LLM._");

  return lines.join("\n");
}

// ---------------------------------------------------------------------------
// Command parser
// ---------------------------------------------------------------------------

function parseCommandName(content: string): string | null {
  const trimmed = content.trim();
  if (!trimmed.startsWith("/")) {
    return null;
  }
  const parts = trimmed.split(/\s+/);
  return parts[0]?.toLowerCase() ?? null;
}

// ---------------------------------------------------------------------------
// Hook
// ---------------------------------------------------------------------------

export interface UseOrchestratorCommandsReturn {
  /**
   * Returns true if the content looks like an orchestrator command.
   */
  isCommand: (content: string) => boolean;

  /**
   * Execute an orchestrator command.
   * Returns a Message with formatted markdown output, or null if not a command.
   */
  executeCommand: (content: string) => Promise<Message | null>;
}

export function useOrchestratorCommands(): UseOrchestratorCommandsReturn {
  const isCommand = useCallback((content: string): boolean => {
    return content.trim().startsWith("/");
  }, []);

  const executeCommand = useCallback(async (content: string): Promise<Message | null> => {
    const command = parseCommandName(content);

    if (!command) {
      return null;
    }

    // /help — local, no network
    if (command === "/help") {
      return makeMessage(formatHelp());
    }

    // /status
    if (command === "/status") {
      try {
        const res = await fetch("/api/orchestrator/health", { method: "GET" });
        const data = (await res.json()) as HealthResponse;
        return makeMessage(formatStatus(data));
      } catch (err) {
        const detail = err instanceof Error ? err.message : "Network error";
        return errorMessage("/status", detail);
      }
    }

    // /agents
    if (command === "/agents") {
      try {
        const res = await fetch("/api/orchestrator/agents", { method: "GET" });
        const data: unknown = await res.json();
        return makeMessage(formatAgents(data));
      } catch (err) {
        const detail = err instanceof Error ? err.message : "Network error";
        return errorMessage("/agents", detail);
      }
    }

    // /jobs or /queue
    if (command === "/jobs" || command === "/queue") {
      try {
        const res = await fetch("/api/orchestrator/queue/stats", { method: "GET" });
        const data = (await res.json()) as QueueStats;
        return makeMessage(formatQueueStats(data));
      } catch (err) {
        const detail = err instanceof Error ? err.message : "Network error";
        return errorMessage(command, detail);
      }
    }

    // /pause
    if (command === "/pause") {
      try {
        const res = await fetch("/api/orchestrator/queue/pause", { method: "POST" });
        const data = (await res.json()) as ActionResponse;
        return makeMessage(formatAction("/pause", data));
      } catch (err) {
        const detail = err instanceof Error ? err.message : "Network error";
        return errorMessage("/pause", detail);
      }
    }

    // /resume
    if (command === "/resume") {
      try {
        const res = await fetch("/api/orchestrator/queue/resume", { method: "POST" });
        const data = (await res.json()) as ActionResponse;
        return makeMessage(formatAction("/resume", data));
      } catch (err) {
        const detail = err instanceof Error ? err.message : "Network error";
        return errorMessage("/resume", detail);
      }
    }

    // Unknown command — show help hint
    return makeMessage(
      `Unknown command: \`${command}\`\n\nType \`/help\` to see available commands.`
    );
  }, []);

  return { isCommand, executeCommand };
}
