/**
 * `EmbedderSettings` — memory/embedder configuration panel (L14 / lot C2).
 *
 * Pure presentation: all behaviour comes from {@link useEmbedder}. Styled with
 * `@/shared` design system tokens; no inline styles, no `invoke()`.
 *
 * Product spirit ("Linux: nothing imposed"):
 * - All strategies are listed on an equal footing: None, ONNX local, Ollama
 *   (localServer), API, Custom.
 * - `e5-small` (ONNX) is only *pre-selected* as the recommended default — the
 *   cursor sits on it, but nothing is written until the user clicks "Save".
 * - A strategy whose Cargo feature flag is `false` (vectorOnnxEnabled /
 *   vectorHttpEnabled) is shown disabled with "not available in this build".
 *   `none` is always available.
 * - "Back to None" is always present.
 * - The change takes effect at the next app start — the panel says so.
 */

import { useEffect, useMemo, useState } from "react";

import type {
  EmbedderProfile,
  EmbedderStrategy,
  RecommendedOnnxEngine,
} from "@/domain";
import { Button, Field, Input, Panel, Spinner, cn } from "@/shared";
import { useEmbedder } from "./useEmbedder";

/** Default endpoint placeholder for a local embedding server (Ollama). */
const LOCAL_SERVER_PLACEHOLDER = "http://localhost:11434/api/embeddings";
const API_ENDPOINT_PLACEHOLDER = "https://api.openai.com/v1/embeddings";

/** The selectable strategies, listed on equal footing. `none` is always last. */
interface StrategyOption {
  strategy: EmbedderStrategy;
  /** Stable selection key (custom shares the `api` strategy but its own form). */
  key: string;
  label: string;
}

const STRATEGY_OPTIONS: StrategyOption[] = [
  { strategy: "none", key: "none", label: "None (naïve recall)" },
  { strategy: "localOnnx", key: "localOnnx", label: "Local ONNX" },
  { strategy: "localServer", key: "localServer", label: "Ollama (local server)" },
  { strategy: "api", key: "api", label: "API" },
  { strategy: "api", key: "custom", label: "Custom" },
];

/** Editable draft of the form, before it is turned into a profile and saved. */
interface Draft {
  id: string;
  name: string;
  model: string;
  endpoint: string;
  apiKeyEnv: string;
  dimension: string;
  /** Selected recommended ONNX engine id (localOnnx). */
  onnxEngineId: string;
}

const EMPTY_DRAFT: Draft = {
  id: "",
  name: "",
  model: "",
  endpoint: "",
  apiKeyEnv: "",
  dimension: "",
  onnxEngineId: "",
};

/** Builds the initial draft for a selection key, given the available engines. */
function draftFor(
  key: string,
  recommendedOnnx: RecommendedOnnxEngine[],
  existing: EmbedderProfile | null,
): Draft {
  if (existing) {
    return {
      id: existing.id,
      name: existing.name,
      model: existing.model ?? "",
      endpoint: existing.endpoint ?? "",
      apiKeyEnv: existing.apiKeyEnv ?? "",
      dimension: String(existing.dimension),
      onnxEngineId:
        key === "localOnnx"
          ? recommendedOnnx.find((e) => e.id === existing.model)?.id ??
            recommendedOnnx[0]?.id ??
            ""
          : "",
    };
  }
  switch (key) {
    case "localOnnx": {
      const reco =
        recommendedOnnx.find((e) => e.recommended) ?? recommendedOnnx[0];
      return {
        ...EMPTY_DRAFT,
        id: "onnx-local",
        name: reco?.displayName ?? "Local ONNX",
        model: reco?.id ?? "",
        dimension: reco ? String(reco.dimension) : "",
        onnxEngineId: reco?.id ?? "",
      };
    }
    case "localServer":
      return {
        ...EMPTY_DRAFT,
        id: "ollama",
        name: "Ollama",
        endpoint: LOCAL_SERVER_PLACEHOLDER,
        model: "nomic-embed-text",
        dimension: "768",
      };
    case "api":
      return {
        ...EMPTY_DRAFT,
        id: "api",
        name: "API embedder",
        endpoint: API_ENDPOINT_PLACEHOLDER,
        apiKeyEnv: "OPENAI_API_KEY",
        model: "text-embedding-3-small",
        dimension: "1536",
      };
    case "custom":
      return { ...EMPTY_DRAFT, id: "custom", name: "Custom embedder" };
    default:
      return { ...EMPTY_DRAFT };
  }
}

/** Whether a strategy is compiled into this build (None always is). */
function strategyEnabled(
  strategy: EmbedderStrategy,
  flags: { vectorOnnxEnabled: boolean; vectorHttpEnabled: boolean },
): boolean {
  switch (strategy) {
    case "none":
      return true;
    case "localOnnx":
      return flags.vectorOnnxEnabled;
    case "localServer":
    case "api":
      return flags.vectorHttpEnabled;
  }
}

export function EmbedderSettings() {
  const vm = useEmbedder();

  // Selection cursor; pre-selected on the recommended ONNX engine. Writing
  // happens only on "Save".
  const [selectedKey, setSelectedKey] = useState<string>("localOnnx");
  const [draft, setDraft] = useState<Draft>(EMPTY_DRAFT);

  const recommendedOnnx = vm.engines?.recommendedOnnx ?? [];
  const flags = {
    vectorOnnxEnabled: vm.engines?.vectorOnnxEnabled ?? false,
    vectorHttpEnabled: vm.engines?.vectorHttpEnabled ?? false,
  };

  // Once the engines load, seed the draft for the current selection (mirroring
  // an existing active profile if its strategy matches the selection).
  useEffect(() => {
    if (!vm.engines) return;
    const opt = STRATEGY_OPTIONS.find((o) => o.key === selectedKey);
    const existing =
      vm.active && opt && vm.active.strategy === opt.strategy ? vm.active : null;
    setDraft(draftFor(selectedKey, vm.engines.recommendedOnnx, existing));
    // We intentionally re-seed only when engines / selection / active change.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [vm.engines, vm.active, selectedKey]);

  const selectedOption = STRATEGY_OPTIONS.find((o) => o.key === selectedKey)!;
  const selectedStrategy = selectedOption.strategy;

  function patch(p: Partial<Draft>) {
    setDraft((d) => ({ ...d, ...p }));
  }

  function selectOnnxEngine(id: string) {
    const eng = recommendedOnnx.find((e) => e.id === id);
    patch({
      onnxEngineId: id,
      model: eng?.id ?? id,
      // Dimension is auto-filled from the chosen model (e5-small ⇒ 384).
      dimension: eng ? String(eng.dimension) : draft.dimension,
    });
  }

  // ── UI-side validation, aligned with the backend (avoid an INVALID error) ──
  const dimensionNum = Number.parseInt(draft.dimension, 10);
  const validation = useMemo(() => {
    if (selectedStrategy === "none") return { ok: true as const };
    if (!draft.id.trim()) return { ok: false as const, msg: "Id is required." };
    if (!draft.name.trim())
      return { ok: false as const, msg: "Name is required." };
    if (!Number.isFinite(dimensionNum) || dimensionNum <= 0)
      return { ok: false as const, msg: "Dimension must be a positive number." };
    if (selectedStrategy === "localServer" || selectedStrategy === "api") {
      if (!draft.endpoint.trim())
        return { ok: false as const, msg: "Endpoint is required." };
    }
    return { ok: true as const };
  }, [selectedStrategy, draft, dimensionNum]);

  function toProfile(): EmbedderProfile {
    return {
      id: draft.id.trim(),
      name: draft.name.trim(),
      strategy: selectedStrategy,
      dimension: dimensionNum,
      model: draft.model.trim() || undefined,
      endpoint:
        selectedStrategy === "localServer" || selectedStrategy === "api"
          ? draft.endpoint.trim() || undefined
          : undefined,
      apiKeyEnv:
        selectedStrategy === "api"
          ? draft.apiKeyEnv.trim() || undefined
          : undefined,
    };
  }

  async function handleSave() {
    if (!validation.ok) return;
    await vm.saveProfile(toProfile());
  }

  async function handleBackToNone() {
    // Delete every configured (non-none) profile so recall falls back to naïve.
    for (const p of vm.profiles) {
      await vm.deleteProfile(p.id);
    }
    setSelectedKey("none");
  }

  const selectClass = cn(
    "h-9 w-full rounded-md bg-raised px-3 text-sm text-content",
    "border border-border outline-none transition-colors",
    "focus:border-primary disabled:cursor-not-allowed disabled:opacity-50",
  );

  const hasActive = vm.active !== null;

  return (
    <Panel title="Memory / Embedder" className="flex flex-col gap-0">
      {vm.error && (
        <p
          role="alert"
          className="mx-4 mt-3 rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-sm text-danger"
        >
          {vm.error}
        </p>
      )}

      <div className="flex flex-col gap-4 p-4">
        {/* ── Restart notice ── */}
        <p
          className="rounded-md border border-border bg-raised px-3 py-2 text-xs text-muted"
          data-testid="embedder-restart-note"
        >
          The embedder change takes effect at the next app start.
        </p>

        {/* ── Active tier (current) ── */}
        <p className="text-xs text-faint" data-testid="embedder-active">
          Current:{" "}
          {hasActive ? (
            <span className="text-content">
              Vector — {vm.active!.strategy}
              {vm.active!.model ? ` ${vm.active!.model}` : ""}
            </span>
          ) : (
            <span className="text-content">Naïve (None)</span>
          )}
        </p>

        {/* ── Strategy chooser ── */}
        <fieldset className="flex flex-col gap-2" aria-label="embedder strategy">
          <legend className="mb-1 text-xs font-semibold uppercase tracking-wide text-faint">
            Strategy
          </legend>
          {STRATEGY_OPTIONS.map((opt) => {
            const enabled = strategyEnabled(opt.strategy, flags);
            const recommended = opt.key === "localOnnx";
            return (
              <label
                key={opt.key}
                className={cn(
                  "flex items-center gap-2 rounded-md border px-3 py-2 text-sm",
                  selectedKey === opt.key
                    ? "border-primary bg-raised"
                    : "border-border",
                  !enabled && "opacity-50",
                )}
                data-testid={`embedder-strategy-${opt.key}`}
              >
                <input
                  type="radio"
                  name="embedder-strategy"
                  value={opt.key}
                  checked={selectedKey === opt.key}
                  disabled={!enabled}
                  onChange={() => setSelectedKey(opt.key)}
                  aria-label={opt.label}
                />
                <span className="text-content">{opt.label}</span>
                {recommended && (
                  <span className="rounded border border-primary/40 bg-primary/10 px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-primary">
                    Recommended
                  </span>
                )}
                {!enabled && (
                  <span className="text-[11px] text-faint">
                    not available in this build
                  </span>
                )}
              </label>
            );
          })}
        </fieldset>

        {/* ── Conditional fields per strategy ── */}
        {selectedStrategy !== "none" && (
          <div className="flex flex-col gap-3">
            {/* localOnnx → model picker + auto dimension */}
            {selectedStrategy === "localOnnx" && (
              <Field label="ONNX model">
                {({ id }) => (
                  <select
                    id={id}
                    aria-label="onnx model"
                    className={selectClass}
                    value={draft.onnxEngineId}
                    disabled={vm.busy}
                    onChange={(e) => selectOnnxEngine(e.target.value)}
                  >
                    {recommendedOnnx.map((eng) => (
                      <option key={eng.id} value={eng.id}>
                        {eng.displayName}
                        {eng.recommended ? " — recommended" : ""} (dim{" "}
                        {eng.dimension}, ~{eng.approxSizeMb} MB)
                      </option>
                    ))}
                  </select>
                )}
              </Field>
            )}

            {/* localServer / api → endpoint */}
            {(selectedStrategy === "localServer" ||
              selectedStrategy === "api") && (
              <Field label="Endpoint">
                {({ id }) => (
                  <Input
                    id={id}
                    aria-label="endpoint"
                    placeholder={
                      selectedStrategy === "localServer"
                        ? LOCAL_SERVER_PLACEHOLDER
                        : API_ENDPOINT_PLACEHOLDER
                    }
                    value={draft.endpoint}
                    disabled={vm.busy}
                    onChange={(e) => patch({ endpoint: e.target.value })}
                  />
                )}
              </Field>
            )}

            {/* api → apiKeyEnv (variable NAME, never the key) */}
            {selectedStrategy === "api" && (
              <Field
                label="API key environment variable"
                hint="Name of the env var holding the key — never the key itself."
              >
                {({ id, describedBy }) => (
                  <Input
                    id={id}
                    aria-label="api key env var"
                    placeholder="OPENAI_API_KEY"
                    aria-describedby={describedBy}
                    value={draft.apiKeyEnv}
                    disabled={vm.busy}
                    onChange={(e) => patch({ apiKeyEnv: e.target.value })}
                  />
                )}
              </Field>
            )}

            {/* model (localServer / api / custom) */}
            {selectedStrategy !== "localOnnx" && (
              <Field label="Model">
                {({ id }) => (
                  <Input
                    id={id}
                    aria-label="model"
                    placeholder="model name"
                    value={draft.model}
                    disabled={vm.busy}
                    onChange={(e) => patch({ model: e.target.value })}
                  />
                )}
              </Field>
            )}

            {/* dimension — auto-filled for ONNX, editable everywhere */}
            <Field
              label="Dimension"
              error={!validation.ok ? validation.msg : undefined}
            >
              {({ id, describedBy }) => (
                <Input
                  id={id}
                  aria-label="dimension"
                  type="number"
                  min={1}
                  value={draft.dimension}
                  aria-describedby={describedBy}
                  disabled={vm.busy}
                  onChange={(e) => patch({ dimension: e.target.value })}
                />
              )}
            </Field>

            {/* id / name (custom & advanced) */}
            <Field label="Profile id">
              {({ id }) => (
                <Input
                  id={id}
                  aria-label="profile id"
                  placeholder="my-embedder"
                  value={draft.id}
                  disabled={vm.busy}
                  onChange={(e) => patch({ id: e.target.value })}
                />
              )}
            </Field>
            <Field label="Profile name">
              {({ id }) => (
                <Input
                  id={id}
                  aria-label="profile name"
                  placeholder="My embedder"
                  value={draft.name}
                  disabled={vm.busy}
                  onChange={(e) => patch({ name: e.target.value })}
                />
              )}
            </Field>
          </div>
        )}

        {/* ── Actions ── */}
        <div className="flex items-center gap-2 border-t border-border pt-3">
          {vm.busy && <Spinner size={14} />}
          {selectedStrategy !== "none" && (
            <Button
              type="button"
              variant="primary"
              aria-label="save embedder"
              disabled={vm.busy || !validation.ok}
              onClick={() => void handleSave()}
            >
              Save
            </Button>
          )}
          <Button
            type="button"
            aria-label="back to none"
            disabled={vm.busy}
            onClick={() => void handleBackToNone()}
          >
            Back to None
          </Button>
        </div>
      </div>
    </Panel>
  );
}
