/**
 * TaskRuntimePanel.tsx — GAP-4: Visualizzazione Operativa
 *
 * Mostra in tempo reale COSA sta facendo l'agente:
 *   - Fase corrente (PLANNING → EXECUTING → VERIFYING → DONE)
 *   - Tool/azione live con label narrativa contestuale
 *   - Timer elapsed
 *   - Timeline compatta step completati (max 4 visibili)
 *   - Reasoning sintetico dell'ultimo step
 *
 * Design:
 *   - Fixed bottom-right, compatto, non invasivo, non overlay sulla chat
 *   - Visibile solo quando task RUNNING o QUEUED — sparisce altrimenti
 *   - Collassabile con click: mostra solo pill di stato
 *   - Mobile-first, Safari iOS safe (AbortController + setTimeout, no AbortSignal.timeout)
 *   - Zero nuove dipendenze: usa useAgentSSE + useTaskStore + selectActiveTask
 *
 * Nessun side effect globale. Cleanup obbligatorio su useEffect.
 */

import { memo, useState, useEffect, useRef, useMemo, useCallback } from "react";
import type * as React from "react";
import { useTaskStore, selectActiveTask } from "@/store/taskStore";
import type { AgentRuntimePhase } from "@/store/taskStore";
import { useAgentSSE }            from "@/hooks/useAgentSSE";
import { TOOL_COLORS, getToolIcon } from "@/components/chat/toolIcons";
import { narrativeLabel }           from "@/lib/agentLoop/toolStatusLabels";
import { Z_INDEX }                  from "@/lib/zindex";

// ─── Keyframes (una volta sola) ───────────────────────────────────────────────
let _kfInjected = false;
function _injectKf() {
  if (_kfInjected || typeof document === "undefined") return;
  _kfInjected = true;
  const el = document.createElement("style");
  el.dataset.id = "trp-kf";
  el.textContent = `
    @keyframes trp-in   { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:none} }
    @keyframes trp-out  { from{opacity:1;transform:none} to{opacity:0;transform:translateY(8px)} }
    @keyframes trp-dot  { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.3;transform:scale(.5)} }
    @keyframes trp-spin { from{transform:rotate(0deg)} to{transform:rotate(360deg)} }
    @keyframes trp-bar  { from{width:0%} to{width:100%} }
    @keyframes trp-fade { from{opacity:0;transform:translateX(-4px)} to{opacity:1;transform:none} }
  `;
  document.head.appendChild(el);
}

// ─── Costanti ─────────────────────────────────────────────────────────────────
const PHASE_META: Record<AgentRuntimePhase, { label: string; color: string; rgb: string; icon: string }> = {
  IDLE:      { label: "In attesa",   color: "#6b7280", rgb: "107,114,128", icon: "○" },
  PLANNING:  { label: "Pianifica",   color: "#818cf8", rgb: "129,140,248", icon: "◈" },
  EXECUTING: { label: "In esecuzione", color: "#34d399", rgb: "52,211,153",  icon: "▶" },
  VERIFYING: { label: "Verifica",    color: "#fbbf24", rgb: "251,191,36",  icon: "◎" },
  DONE:      { label: "Completato",  color: "#4ade80", rgb: "74,222,128",  icon: "✓" },
  ERROR:     { label: "Errore",      color: "#f87171", rgb: "248,113,113", icon: "✕" },
};

const INTERNAL_TOOLS = new Set([
  "__plan__", "__thinking__", "__verify__", "__belief_revision__", "__plan_tracker__",
]);

// ─── Elapsed timer (Safari-safe, nessun AbortSignal.timeout) ─────────────────
const ElapsedTimer = memo(({ startMs }: { startMs: number }) => {
  const [elapsed, setElapsed] = useState(0);
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  useEffect(() => {
    setElapsed(Date.now() - startMs);
    timerRef.current = setInterval(() => {
      setElapsed(Date.now() - startMs);
    }, 200);
    return () => {
      if (timerRef.current !== null) {
        clearInterval(timerRef.current);
        timerRef.current = null;
      }
    };
  }, [startMs]);

  if (elapsed < 1000) return <>{elapsed}ms</>;
  if (elapsed < 60_000) return <>{(elapsed / 1000).toFixed(1)}s</>;
  const m = Math.floor(elapsed / 60_000);
  const s = Math.floor((elapsed % 60_000) / 1000);
  return <>{m}m{s > 0 ? ` ${s}s` : ""}</>;
});
ElapsedTimer.displayName = "ElapsedTimer";

// ─── Barra di fase compatta ───────────────────────────────────────────────────
const PHASE_ORDER: AgentRuntimePhase[] = ["PLANNING", "EXECUTING", "VERIFYING", "DONE"];

const PhaseStepper = memo(({ phase }: { phase: AgentRuntimePhase }) => {
  const activeIdx = PHASE_ORDER.indexOf(phase);

  return (
    <div style={{ display: "flex", alignItems: "center", gap: 0, width: "100%" }}>
      {PHASE_ORDER.map((p, i) => {
        const meta   = PHASE_META[p];
        const isDone = activeIdx > i;
        const isActive = activeIdx === i;
        return (
          <div key={p} style={{ display: "flex", alignItems: "center", flex: 1, minWidth: 0 }}>
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 3, flex: 1 }}>
              <div style={{
                width: 16, height: 16, borderRadius: "50%",
                display: "flex", alignItems: "center", justifyContent: "center",
                background: isDone
                  ? `rgba(${meta.rgb},.18)`
                  : isActive
                  ? `rgba(${meta.rgb},.12)`
                  : "rgba(255,255,255,.04)",
                border: isDone
                  ? `1.5px solid ${meta.color}`
                  : isActive
                  ? `1.5px solid rgba(${meta.rgb},.60)`
                  : "1px solid rgba(255,255,255,.09)",
                color: isDone || isActive ? meta.color : "rgba(255,255,255,.18)",
                transition: "all .25s ease",
                animation: isActive && phase !== "DONE" && phase !== "ERROR"
                  ? "trp-dot 1.6s ease-in-out infinite" : undefined,
              }}>
                {isDone ? (
                  <svg width={8} height={8} viewBox="0 0 24 24" fill="none"
                    stroke={meta.color} strokeWidth={3.5} strokeLinecap="round">
                    <polyline points="20 6 9 17 4 12"/>
                  </svg>
                ) : (
                  <span style={{ fontSize: "0.48rem", fontWeight: 700 }}>{i + 1}</span>
                )}
              </div>
              <span style={{
                fontSize: "0.52rem", fontWeight: isActive ? 600 : 400,
                color: isDone
                  ? `rgba(${meta.rgb},.65)`
                  : isActive ? meta.color : "rgba(148,163,184,.22)",
                letterSpacing: ".03em", whiteSpace: "nowrap",
                transition: "color .2s",
              }}>
                {meta.label}
              </span>
            </div>
            {i < PHASE_ORDER.length - 1 && (
              <div style={{
                height: 1, width: "100%", maxWidth: 18, flexShrink: 0,
                background: isDone
                  ? `rgba(${meta.rgb},.35)` : "rgba(255,255,255,.06)",
                transition: "background .3s", marginBottom: 16,
              }} />
            )}
          </div>
        );
      })}
    </div>
  );
});
PhaseStepper.displayName = "PhaseStepper";

// ─── Pill compatta (stato collassato) ─────────────────────────────────────────
const CollapsedPill = memo(({ phase, toolLabel, startMs, onClick }: {
  phase:     AgentRuntimePhase;
  toolLabel: string;
  startMs:   number;
  onClick:   () => void;
}) => {
  const meta = PHASE_META[phase];
  return (
    <button
      onClick={onClick}
      title="Espandi pannello operativo"
      style={{
        all: "unset", cursor: "pointer",
        display: "flex", alignItems: "center", gap: 7,
        padding: "6px 11px", borderRadius: 20,
        background: "rgba(12,14,28,.92)",
        border: `1px solid rgba(${meta.rgb},.25)`,
        boxShadow: `0 2px 12px rgba(0,0,0,.45), 0 0 0 1px rgba(${meta.rgb},.08)`,
        backdropFilter: "blur(8px)", WebkitBackdropFilter: "blur(8px)",
        animation: "trp-in .22s ease",
        WebkitTapHighlightColor: "transparent",
      } as React.CSSProperties}
    >
      <div style={{
        width: 7, height: 7, borderRadius: "50%",
        background: meta.color,
        animation: phase !== "DONE" && phase !== "ERROR"
          ? "trp-dot 1.4s ease-in-out infinite" : undefined,
        flexShrink: 0,
      }} />
      <span style={{ fontSize: ".72rem", color: "rgba(226,232,240,.78)", fontWeight: 500, maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
        {toolLabel}
      </span>
      <span style={{ fontSize: ".63rem", fontFamily: "ui-monospace,monospace", color: `rgba(${meta.rgb},.6)`, flexShrink: 0 }}>
        <ElapsedTimer startMs={startMs} />
      </span>
    </button>
  );
});
CollapsedPill.displayName = "CollapsedPill";

// ─── Componente principale ────────────────────────────────────────────────────
function TaskRuntimePanel() {
  _injectKf();

  const activeTask    = useTaskStore(selectActiveTask);
  const { steps, isLive } = useAgentSSE(activeTask?.id ?? undefined);

  const [collapsed, setCollapsed]   = useState(true);
  const [visible,   setVisible]     = useState(false);
  const fadeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Apri/chiudi pannello in base a isLive
  useEffect(() => {
    if (fadeTimerRef.current !== null) {
      clearTimeout(fadeTimerRef.current);
      fadeTimerRef.current = null;
    }
    if (isLive) {
      setVisible(true);
    } else {
      // Ritardo sparizione: mostra "Completato" per 2.5s
      fadeTimerRef.current = setTimeout(() => {
        setVisible(false);
        fadeTimerRef.current = null;
      }, 2500);
    }
    return () => {
      if (fadeTimerRef.current !== null) {
        clearTimeout(fadeTimerRef.current);
        fadeTimerRef.current = null;
      }
    };
  }, [isLive]);

  const toggle = useCallback(() => setCollapsed(c => !c), []);

  // Step visibili (no internal) ordinati
  const visibleSteps = useMemo(
    () => steps.filter(s => !INTERNAL_TOOLS.has(s.tool)),
    [steps],
  );

  const runningStep = useMemo(
    () => visibleSteps.find(s => s.status === "running") ?? null,
    [visibleSteps],
  );
  const doneSteps = useMemo(
    () => visibleSteps.filter(s => s.status === "done").slice(-4),
    [visibleSteps],
  );

  // Fase corrente
  const phase: AgentRuntimePhase = useMemo(() => {
    if (!activeTask) return "IDLE";
    if (activeTask.runtimePhase) return activeTask.runtimePhase;
    if (!isLive) return "DONE";
    if (runningStep) {
      const t = runningStep.tool;
      if (["__plan__", "planning", "plan", "__thinking__", "__belief_revision__"].includes(t))
        return "PLANNING";
      if (["__verify__", "goal_verifier", "_runtime_verifier", "_build_validator"].includes(t))
        return "VERIFYING";
      return "EXECUTING";
    }
    return "EXECUTING";
  }, [activeTask, isLive, runningStep]);

  const phaseMeta = PHASE_META[phase];

  // Label strumento attivo con narrativa contestuale
  const toolLabel = useMemo(() => {
    if (!isLive) return "Completato";
    if (!runningStep) return phaseMeta.label;
    return narrativeLabel(runningStep.tool, (runningStep.args ?? {}) as Record<string, unknown>);
  }, [isLive, runningStep, phaseMeta.label]);

  // Color dello step running
  const runningColor = runningStep
    ? (TOOL_COLORS[runningStep.tool] ?? phaseMeta.color)
    : phaseMeta.color;
  const runningRgb = runningColor.startsWith("#")
    ? `${parseInt(runningColor.slice(1,3),16)},${parseInt(runningColor.slice(3,5),16)},${parseInt(runningColor.slice(5,7),16)}`
    : phaseMeta.rgb;

  // Snippet reasoning dell'ultimo step done
  const reasoningSnippet = useMemo(() => {
    const last = doneSteps[doneSteps.length - 1];
    if (!last) return null;
    const r = typeof last.result === "string" ? last.result : "";
    const clean = r.replace(/^(✅|⚠️|❌)\s*(VERIFICATO|VERIFICA|ERRORE):\s*/i, "").trim();
    return clean.length > 6 ? (clean.length > 70 ? clean.slice(0, 70) + "…" : clean) : null;
  }, [doneSteps]);

  const startMs = activeTask?.startedAt ?? Date.now();

  if (!visible || !activeTask) return null;

  // ── Pill collassata ──────────────────────────────────────────────────────
  if (collapsed) {
    return (
      <div style={{
        position: "fixed",
        bottom: 84,  // sopra la input bar
        right: 14,
        zIndex: Z_INDEX.NOTIFICATION,
        pointerEvents: "auto",
      }}>
        <CollapsedPill
          phase={phase}
          toolLabel={toolLabel}
          startMs={startMs}
          onClick={toggle}
        />
      </div>
    );
  }

  // ── Pannello espanso ──────────────────────────────────────────────────────
  return (
    <div
      style={{
        position: "fixed",
        bottom: 84,
        right: 14,
        width: 288,
        zIndex: Z_INDEX.NOTIFICATION,
        background: "rgba(10,12,26,.95)",
        border: `1px solid rgba(${phaseMeta.rgb},.20)`,
        borderRadius: 14,
        boxShadow: `0 8px 28px rgba(0,0,0,.55), 0 0 0 1px rgba(${phaseMeta.rgb},.06)`,
        backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)",
        overflow: "hidden",
        animation: "trp-in .18s ease",
        pointerEvents: "auto",
      } as React.CSSProperties}
    >
      {/* ── Header ── */}
      <div style={{
        padding: "9px 12px 7px",
        borderBottom: "1px solid rgba(255,255,255,.06)",
        display: "flex", alignItems: "center", gap: 7,
      }}>
        {/* Icona fase */}
        <div style={{
          width: 22, height: 22, borderRadius: 7, flexShrink: 0,
          display: "flex", alignItems: "center", justifyContent: "center",
          background: `rgba(${phaseMeta.rgb},.12)`,
          border: `1px solid rgba(${phaseMeta.rgb},.28)`,
          animation: isLive && phase !== "DONE" && phase !== "ERROR"
            ? "trp-dot 1.6s ease-in-out infinite" : undefined,
        }}>
          <span style={{ fontSize: ".72rem", color: phaseMeta.color, lineHeight: 1 }}>
            {phaseMeta.icon}
          </span>
        </div>

        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: ".72rem", fontWeight: 600, color: "rgba(226,232,240,.85)", lineHeight: 1.3 }}>
            {isLive ? phaseMeta.label : "Completato"}
          </div>
          <div style={{ fontSize: ".60rem", color: `rgba(${phaseMeta.rgb},.55)`, fontFamily: "ui-monospace,monospace", lineHeight: 1.2, marginTop: 1 }}>
            <ElapsedTimer startMs={startMs} />
          </div>
        </div>

        {/* Collapse button */}
        <button
          onClick={toggle}
          title="Comprimi"
          style={{
            all: "unset", cursor: "pointer",
            width: 20, height: 20, borderRadius: 6,
            display: "flex", alignItems: "center", justifyContent: "center",
            color: "rgba(148,163,184,.4)",
            transition: "color .15s",
            WebkitTapHighlightColor: "transparent",
          } as React.CSSProperties}
          onMouseEnter={e => { (e.currentTarget as HTMLElement).style.color = "rgba(148,163,184,.8)"; }}
          onMouseLeave={e => { (e.currentTarget as HTMLElement).style.color = "rgba(148,163,184,.4)"; }}
        >
          <svg width={11} height={11} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2.5} strokeLinecap="round">
            <polyline points="6 9 12 15 18 9"/>
          </svg>
        </button>
      </div>

      {/* ── Stepper fasi ── */}
      <div style={{ padding: "8px 12px 4px" }}>
        <PhaseStepper phase={phase} />
      </div>

      {/* ── Tool attivo ── */}
      {isLive && runningStep && (
        <div style={{
          margin: "0 10px 8px",
          padding: "7px 10px",
          borderRadius: 10,
          background: `rgba(${runningRgb},.07)`,
          border: `1px solid rgba(${runningRgb},.18)`,
          animation: "trp-fade .18s ease",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
            {/* Icona tool */}
            <div style={{
              width: 20, height: 20, borderRadius: 6, flexShrink: 0,
              display: "flex", alignItems: "center", justifyContent: "center",
              background: `rgba(${runningRgb},.14)`,
              border: `1px solid rgba(${runningRgb},.30)`,
              color: runningColor,
            }}>
              {getToolIcon(runningStep.tool, 11)}
            </div>

            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: ".70rem", fontWeight: 500, color: "rgba(226,232,240,.80)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                {toolLabel}
              </div>
              {runningStep.explanation && (
                <div style={{ fontSize: ".60rem", color: `rgba(${runningRgb},.45)`, marginTop: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                  {runningStep.explanation.length > 52
                    ? runningStep.explanation.slice(0, 52) + "…"
                    : runningStep.explanation}
                </div>
              )}
            </div>

            {/* Spinner */}
            <div style={{
              width: 12, height: 12, flexShrink: 0,
              border: `1.5px solid rgba(${runningRgb},.18)`,
              borderTopColor: runningColor,
              borderRadius: "50%",
              animation: "trp-spin .8s linear infinite",
            }} />
          </div>
        </div>
      )}

      {/* ── Timeline step completati (max 4) ── */}
      {doneSteps.length > 0 && (
        <div style={{ padding: "0 10px 8px", display: "flex", flexDirection: "column", gap: 0 }}>
          {doneSteps.map((step, i) => {
            const isLast = i === doneSteps.length - 1;
            const sc = TOOL_COLORS[step.tool] ?? "#818cf8";
            const sr = sc.startsWith("#")
              ? `${parseInt(sc.slice(1,3),16)},${parseInt(sc.slice(3,5),16)},${parseInt(sc.slice(5,7),16)}`
              : "129,140,248";
            return (
              <div key={`${step.tool}-${i}`} style={{ display: "flex", gap: 7, alignItems: "flex-start", minHeight: 22 }}>
                {/* Linea verticale + dot */}
                <div style={{ display: "flex", flexDirection: "column", alignItems: "center", width: 14, flexShrink: 0, paddingTop: 2 }}>
                  <div style={{
                    width: 12, height: 12, borderRadius: "50%",
                    display: "flex", alignItems: "center", justifyContent: "center",
                    background: `rgba(${sr},.08)`,
                    border: `1px solid rgba(${sr},.22)`,
                  }}>
                    <svg width={6} height={6} viewBox="0 0 24 24" fill="none"
                      stroke="#4ade80" strokeWidth={3.5} strokeLinecap="round">
                      <polyline points="20 6 9 17 4 12"/>
                    </svg>
                  </div>
                  {!isLast && (
                    <div style={{ width: 1, flex: 1, minHeight: 4, background: "rgba(255,255,255,.06)", marginTop: 2 }} />
                  )}
                </div>
                {/* Label */}
                <div style={{ flex: 1, minWidth: 0, paddingBottom: isLast ? 0 : 6 }}>
                  <span style={{
                    fontSize: ".66rem",
                    color: "rgba(148,163,184,.42)",
                    overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
                    display: "block",
                  }}>
                    {narrativeLabel(step.tool, (step.args ?? {}) as Record<string, unknown>)
                      .replace(/…$/, "")}
                  </span>
                </div>
                {/* Durata */}
                {step.durationMs != null && (
                  <span style={{ fontSize: ".57rem", fontFamily: "ui-monospace,monospace", color: "rgba(100,116,139,.30)", flexShrink: 0, paddingTop: 1 }}>
                    {step.durationMs < 1000
                      ? `${step.durationMs}ms`
                      : `${(step.durationMs / 1000).toFixed(1)}s`}
                  </span>
                )}
              </div>
            );
          })}
        </div>
      )}

      {/* ── Reasoning snippet ── */}
      {reasoningSnippet && !isLive && (
        <div style={{
          margin: "0 10px 9px",
          padding: "6px 9px",
          borderRadius: 8,
          background: "rgba(255,255,255,.025)",
          border: "1px solid rgba(255,255,255,.06)",
        }}>
          <div style={{ fontSize: ".60rem", color: "#4a4a6a", marginBottom: 3, textTransform: "uppercase", letterSpacing: ".06em", fontWeight: 600 }}>
            Risultato
          </div>
          <div style={{ fontSize: ".66rem", color: "rgba(148,163,184,.55)", lineHeight: 1.55 }}>
            {reasoningSnippet}
          </div>
        </div>
      )}

      {/* ── Progress bar live ── */}
      {isLive && (
        <div style={{ height: 2, background: "rgba(255,255,255,.04)", position: "relative", overflow: "hidden" }}>
          <div style={{
            position: "absolute", top: 0, left: 0, height: "100%",
            background: `linear-gradient(90deg, rgba(${phaseMeta.rgb},.0), rgba(${phaseMeta.rgb},.7), rgba(${phaseMeta.rgb},.0))`,
            width: "40%",
            animation: "trp-bar 1.8s ease-in-out infinite alternate",
          }} />
        </div>
      )}
    </div>
  );
}

export default memo(TaskRuntimePanel);
