/**
 * `ModelServerLaunchBadge` — presentational launch-state indicator for an agent
 * whose OpenCode profile binds a local model server (F35.1). All state is folded
 * in {@link useAgents} (`modelServerStatusByServer` + `launchFailureByAgent`);
 * this component only renders it.
 *
 * It shows, in order of severity:
 *  - a launch **failure** with its actionable message (not a bare "agent failed")
 *    — the full logs are never shown by default; a "Détails" toggle reveals the
 *    stable code/cause only;
 *  - otherwise the model-server lifecycle: `probing`, `starting`, `ready`
 *    (distinguishing a reused server from a freshly-started one).
 *
 * Renders nothing when there is neither a status to show nor a failure, so a
 * plain (non-local-model) agent row stays untouched.
 */

import { useState } from "react";

import { cn } from "@/shared";
import type { ModelServerStatus } from "@/domain";
import type { AgentLaunchFailure } from "./useAgents";

export interface ModelServerLaunchBadgeProps {
  /** The bound server's lifecycle status, when one has been observed. */
  status?: ModelServerStatus;
  /** The agent's last launch failure, when one occurred. */
  failure?: AgentLaunchFailure;
}

/** Human label + tone for a non-failed lifecycle state. */
function describeStatus(
  status: ModelServerStatus,
): { label: string; tone: string; role?: "status" } | null {
  switch (status.state) {
    case "notConfigured":
      return null; // Nothing to surface for an unmanaged endpoint.
    case "probing":
      return { label: "vérification du serveur…", tone: "bg-muted/20 text-muted", role: "status" };
    case "starting":
      return { label: "démarrage du serveur…", tone: "bg-warning/20 text-warning", role: "status" };
    case "downloading":
      return { label: "téléchargement du modèle…", tone: "bg-warning/20 text-warning", role: "status" };
    case "ready":
      return status.reused
        ? { label: "serveur prêt (réutilisé)", tone: "bg-success/20 text-success" }
        : { label: "serveur prêt", tone: "bg-success/20 text-success" };
    case "failed":
      // Handled by the failure branch below (richer, actionable).
      return null;
  }
}

export function ModelServerLaunchBadge({
  status,
  failure,
}: ModelServerLaunchBadgeProps) {
  const [showDetail, setShowDetail] = useState(false);

  // A launch failure (from `agentLaunchFailed`) or a `failed` status both mean
  // the launch could not complete — prefer the agent-scoped failure (it carries
  // the actionable message); fall back to the server `failed` status.
  const failed: { code: string; message: string; cause?: string } | null =
    failure
      ? failure
      : status?.state === "failed"
        ? { code: status.code, message: status.message }
        : null;

  if (failed) {
    return (
      <span className="flex min-w-0 flex-wrap items-center gap-2">
        <span
          role="alert"
          aria-label="model server launch failed"
          className={cn(
            "rounded-full px-2 py-0.5 text-xs font-medium",
            "bg-danger/20 text-danger",
          )}
        >
          Échec du lancement : {failed.message}
        </span>
        <button
          type="button"
          aria-label="toggle launch failure detail"
          onClick={() => setShowDetail((v) => !v)}
          className="text-xs text-muted underline hover:text-content"
        >
          Détails
        </button>
        {showDetail && (
          <span aria-label="launch failure detail" className="text-xs text-faint">
            code&nbsp;{failed.code}
            {failed.cause ? ` · cause ${failed.cause}` : ""}
          </span>
        )}
      </span>
    );
  }

  if (!status) return null;
  const described = describeStatus(status);
  if (!described) return null;

  return (
    <span
      role={described.role}
      aria-label="model server status"
      className={cn(
        "rounded-full px-2 py-0.5 text-xs font-medium",
        described.tone,
      )}
    >
      {described.label}
    </span>
  );
}
