"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useLocale, useTranslations } from "next-intl";
import {
  Activity,
  AlertTriangle,
  Bot,
  BrainCircuit,
  CheckCircle2,
  MessageSquareText,
  RefreshCw,
  Rocket,
  SearchCheck,
  ShieldCheck,
  Wrench,
} from "lucide-react";

import { AppLayout } from "@/components/layout";
import { getRuntimeApiBaseUrl } from "@/lib/runtime-api-base";
import { cn } from "@/lib/utils";

type SceneStatus = "loading" | "ready" | "degraded";

type SceneZone = {
  zone_id: string;
  label: string;
  kind: string;
  position: { x: number; y: number };
};

type SceneAgent = {
  agent_id: string;
  label: string;
  zone_id: string;
  state: string;
  animation: string;
  position: { x: number; y: number };
  current_task?: {
    stage_id?: string | null;
    recorded?: boolean | null;
    total?: number | null;
    recent?: number | null;
    feeds_learning?: boolean | null;
    required_for_closed_loop?: boolean | null;
  };
};

type SceneWorkItem = {
  work_item_id: string;
  title: string;
  priority: string;
  status: string;
  zone_id: string;
  animation: string;
  position: { x: number; y: number };
  next_controlled_action?: string | null;
  exit_criteria?: string | null;
};

type SceneState = {
  schema_version: "openclaw_live_ops_scene_state_v1";
  generated_at: string;
  status: string;
  source: {
    deploy_readback_marker?: string | null;
    live_source_connected?: boolean | null;
  };
  room: {
    zones: SceneZone[];
    animation_loop: {
      enabled: boolean;
      tick_ms: number;
      motion_model: string;
    };
  };
  agents: SceneAgent[];
  work_items: SceneWorkItem[];
  rollups: {
    zone_count: number;
    agent_count: number;
    work_item_count: number;
    animated_entity_count: number;
    completed_work_item_count: number;
    blocked_work_item_count: number;
    source_stage_count: number;
    recorded_stage_count: number;
  };
  boundaries: Record<string, boolean>;
};

const API_BASE = getRuntimeApiBaseUrl();

const zoneIconByKind: Record<string, typeof Activity> = {
  control_plane: BrainCircuit,
  tool_context: Wrench,
  knowledge_retrieval: SearchCheck,
  procedure_trust: ShieldCheck,
  post_apply_verification: CheckCircle2,
  receipt_delivery: MessageSquareText,
  release_truth: Rocket,
};

function stateLabel(t: ReturnType<typeof useTranslations>, state: string): string {
  if (state === "working") return t("states.working");
  if (state === "verified") return t("states.verified");
  if (state === "blocked") return t("states.blocked");
  if (state === "waiting") return t("states.waiting");
  return t("states.idle");
}

function stateClass(state: string): string {
  if (state === "working") return "border-[#4a90d9] bg-[#eef5ff] text-[#1f5b9b]";
  if (state === "verified") return "border-[#8fc29a] bg-[#f0faf2] text-[#17602a]";
  if (state === "blocked") return "border-[#e2a29b] bg-[#fff0ef] text-[#9f2f25]";
  if (state === "waiting") return "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]";
  return "border-[#d8d3c7] bg-white text-[#5f5b52]";
}

function stateFromWorkItemStatus(status: string): string {
  if (status === "completed") return "verified";
  if (status === "in_progress") return "working";
  if (status === "blocked") return "blocked";
  return "waiting";
}

function shortValue(value?: string | null): string {
  if (!value) return "--";
  return value.length > 18 ? `${value.slice(0, 14)}...` : value;
}

function formatNumber(value: number | null | undefined): string {
  return new Intl.NumberFormat("zh-TW").format(Number(value ?? 0));
}

export default function OpenClawLiveOpsSpacePage({
  params,
}: {
  params: { locale: string };
}) {
  const t = useTranslations("openclaw.liveOpsSpace");
  const locale = useLocale();
  const [scene, setScene] = useState<SceneState | null>(null);
  const [status, setStatus] = useState<SceneStatus>("loading");
  const [updatedAt, setUpdatedAt] = useState<Date | null>(null);

  const fetchSceneState = useCallback(async () => {
    if (!API_BASE) {
      setStatus("degraded");
      return;
    }
    const controller = new AbortController();
    const timeout = window.setTimeout(() => controller.abort(), 12_000);
    try {
      const response = await fetch(
        `${API_BASE}/api/v1/agents/openclaw-live-ops-scene-state`,
        { cache: "no-store", signal: controller.signal },
      );
      if (!response.ok) {
        setStatus("degraded");
        return;
      }
      const payload = (await response.json()) as SceneState;
      setScene(payload);
      setUpdatedAt(new Date());
      setStatus("ready");
    } catch {
      setStatus("degraded");
    } finally {
      window.clearTimeout(timeout);
    }
  }, []);

  useEffect(() => {
    void fetchSceneState();
    const timer = window.setInterval(fetchSceneState, 15_000);
    return () => window.clearInterval(timer);
  }, [fetchSceneState]);

  const zones = scene?.room.zones ?? [];
  const agents = scene?.agents ?? [];
  const workItems = scene?.work_items ?? [];
  const boundaryOk = useMemo(() => {
    if (!scene) return false;
    return [
      "raw_session_read_allowed",
      "sqlite_read_allowed",
      "secret_value_display_allowed",
      "runtime_action_performed",
      "host_or_k8s_write_performed",
    ].every((key) => scene.boundaries[key] === false);
  }, [scene]);
  const packetSlots = useMemo(() => {
    const count = Math.max(8, Math.min(14, scene?.rollups.animated_entity_count ?? 10));
    return Array.from({ length: count }, (_, index) => index);
  }, [scene]);
  const animationLoopEnabled = scene?.room.animation_loop.enabled === true;

  return (
    <AppLayout locale={params.locale} fullBleed>
      <main className="min-h-screen overflow-x-hidden bg-[#f7f8f7] text-[#141413]">
        <div className="mx-auto flex w-full max-w-[1520px] flex-col gap-4 px-3 py-4 lg:px-5">
          <section className="grid min-w-0 items-start gap-4 lg:grid-cols-[minmax(0,1fr)_360px]">
            <div className="min-w-0 border border-[#d8d3c7] bg-white">
              <div className="flex min-w-0 flex-wrap items-center justify-between gap-3 border-b border-[#e5e1d8] px-4 py-3">
                <div className="min-w-0">
                  <p className="text-xs font-semibold uppercase text-[#77736a]">
                    OpenClaw
                  </p>
                  <h1 className="mt-1 break-words text-2xl font-semibold leading-tight text-[#141413] sm:text-3xl">
                    {t("title")}
                  </h1>
                </div>
                <div className="flex items-center gap-2">
                  <span
                    className={cn(
                      "inline-flex items-center gap-2 border px-3 py-1.5 text-xs font-semibold",
                      status === "ready"
                        ? "border-[#8fc29a] bg-[#f0faf2] text-[#17602a]"
                        : "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]",
                    )}
                  >
                    {status === "ready" ? (
                      <CheckCircle2 className="h-4 w-4" aria-hidden="true" />
                    ) : (
                      <AlertTriangle className="h-4 w-4" aria-hidden="true" />
                    )}
                    {status === "ready"
                      ? t("status.ready")
                      : status === "loading"
                        ? t("status.loading")
                        : t("status.degraded")}
                  </span>
                  <button
                    type="button"
                    onClick={() => void fetchSceneState()}
                    className="inline-flex h-9 w-9 items-center justify-center border border-[#d8d3c7] bg-white text-[#4f4b44] transition hover:border-[#4a90d9] hover:text-[#1f5b9b]"
                    title={t("actions.refresh")}
                    aria-label={t("actions.refresh")}
                  >
                    <RefreshCw className="h-4 w-4" aria-hidden="true" />
                  </button>
                </div>
              </div>

              <div
                data-testid="openclaw-live-ops-room"
                className="relative aspect-[16/10] min-h-[420px] overflow-hidden bg-[#e8eff3] sm:min-h-[560px]"
              >
                <div className="absolute inset-x-[3%] bottom-[4%] top-[7%] rotate-[-2deg] skew-y-[-7deg] border border-[#b7c8d0] bg-[#fdfefe] shadow-[0_30px_80px_rgba(37,55,68,0.18)]" />
                <div className="absolute inset-x-[5%] bottom-[9%] top-[11%] rotate-[-2deg] skew-y-[-7deg] bg-[linear-gradient(90deg,rgba(74,144,217,0.14)_1px,transparent_1px),linear-gradient(0deg,rgba(74,144,217,0.11)_1px,transparent_1px)] bg-[size:44px_44px]" />
                <div className="absolute left-[8%] top-[10%] h-[13%] w-[84%] rotate-[-2deg] skew-y-[-7deg] border border-[#c6d1d5] bg-[#e9eee8]" />
                <div className="absolute left-[14%] top-[14%] h-10 w-[17%] rotate-[-2deg] skew-y-[-7deg] border border-[#aebbc0] bg-[#26333a] shadow-[0_10px_22px_rgba(37,55,68,0.22)]">
                  <span className="openclaw-screen-sweep absolute inset-0" />
                  <span className="absolute left-2 top-2 h-1.5 w-14 bg-[#70d6a4]" />
                  <span className="absolute bottom-2 left-2 h-1.5 w-9 bg-[#f0bd69]" />
                </div>
                <div className="absolute right-[14%] top-[14%] h-10 w-[17%] rotate-[-2deg] skew-y-[-7deg] border border-[#aebbc0] bg-[#26333a] shadow-[0_10px_22px_rgba(37,55,68,0.22)]">
                  <span className="openclaw-screen-sweep absolute inset-0" />
                  <span className="absolute left-2 top-2 h-1.5 w-11 bg-[#8fc29a]" />
                  <span className="absolute bottom-2 left-2 h-1.5 w-16 bg-[#4a90d9]" />
                </div>

                <div className="absolute left-1/2 top-[48%] h-[19%] w-[30%] -translate-x-1/2 -translate-y-1/2 rotate-[-2deg] skew-y-[-7deg] border border-[#b7b0a5] bg-[#ead9bd] shadow-[0_22px_42px_rgba(63,49,34,0.16)]" />
                <div className="absolute left-1/2 top-[46%] h-[10%] w-[20%] -translate-x-1/2 -translate-y-1/2 rotate-[-2deg] skew-y-[-7deg] border border-[#87939a] bg-[#27333a] shadow-[0_14px_28px_rgba(37,55,68,0.2)]">
                  <span className="absolute left-3 top-3 h-1.5 w-16 bg-[#4a90d9]" />
                  <span className="absolute bottom-3 right-3 h-1.5 w-12 bg-[#8fc29a]" />
                </div>
                <div className="absolute left-[25%] top-[77%] h-[9%] w-[15%] rotate-[-2deg] skew-y-[-7deg] border border-[#b7b0a5] bg-[#d6c8aa]" />
                <div className="absolute right-[20%] top-[76%] h-[10%] w-[12%] rotate-[-2deg] skew-y-[-7deg] border border-[#b7b0a5] bg-[#d8e5df]" />

                {packetSlots.map((slot) => (
                  <span
                    key={slot}
                    data-testid="openclaw-flow-packet"
                    className="openclaw-flow-packet absolute h-2.5 w-2.5 border border-[#f0bd69] bg-[#fff6c7] shadow-[0_0_18px_rgba(240,189,105,0.5)]"
                    style={{
                      left: `${14 + (slot % 7) * 11}%`,
                      top: `${28 + (slot % 4) * 12}%`,
                      animationDelay: `${slot * 0.34}s`,
                      animationDuration: `${5.2 + (slot % 4) * 0.5}s`,
                    }}
                  />
                ))}

                {zones.map((zone) => {
                  const Icon = zoneIconByKind[zone.kind] ?? Activity;
                  return (
                    <div
                      key={zone.zone_id}
                      data-testid="openclaw-zone"
                      className="absolute flex h-14 w-28 -translate-x-1/2 -translate-y-1/2 rotate-[-2deg] items-center gap-2 border border-[#cbd4d8] bg-white/95 px-2 shadow-[0_10px_24px_rgba(54,72,88,0.12)] backdrop-blur"
                      style={{ left: `${zone.position.x}%`, top: `${zone.position.y}%` }}
                    >
                      <span className="flex h-8 w-8 shrink-0 items-center justify-center border border-[#d8d3c7] bg-[#f7f8f7] text-[#4a90d9]">
                        <Icon className="h-4 w-4" aria-hidden="true" />
                      </span>
                      <span className="min-w-0 truncate text-[11px] font-semibold text-[#34302a]">
                        {zone.label}
                      </span>
                    </div>
                  );
                })}

                {workItems.map((item, index) => (
                  <div
                    key={item.work_item_id}
                    data-testid="openclaw-work-token"
                    className={cn(
                      "openclaw-work-token absolute h-8 w-20 -translate-x-1/2 -translate-y-1/2 border px-2 py-1 text-[10px] font-semibold shadow-[0_8px_20px_rgba(54,72,88,0.16)]",
                      stateClass(stateFromWorkItemStatus(item.status)),
                    )}
                    style={{
                      left: `${item.position.x}%`,
                      top: `${item.position.y}%`,
                      animationDelay: `${index * 0.35}s`,
                    }}
                  >
                    <span className="block truncate">{item.work_item_id}</span>
                  </div>
                ))}

                {agents.map((agent, index) => (
                  <div
                    key={agent.agent_id}
                    data-testid="openclaw-agent-avatar"
                    className="openclaw-agent absolute -translate-x-1/2 -translate-y-1/2"
                    style={{
                      left: `${agent.position.x}%`,
                      top: `${agent.position.y}%`,
                      animationDelay: `${index * 0.28}s`,
                    }}
                  >
                    <div
                      className={cn(
                        "relative flex h-14 w-14 items-center justify-center border-2 bg-white shadow-[0_16px_30px_rgba(54,72,88,0.2)]",
                        stateClass(agent.state),
                      )}
                    >
                      <span
                        className={cn(
                          "absolute -right-1 -top-1 h-3 w-3 border border-white",
                          agent.state === "blocked"
                            ? "bg-[#d95f4f]"
                            : agent.state === "verified"
                              ? "bg-[#4f9b62]"
                              : agent.state === "working"
                                ? "bg-[#4a90d9]"
                                : "bg-[#f0bd69]",
                        )}
                      />
                      <Bot className="h-6 w-6" aria-hidden="true" />
                    </div>
                    <div className="mt-1 max-w-28 truncate border border-[#d8d3c7] bg-white px-1.5 py-0.5 text-center text-[10px] font-semibold text-[#34302a] shadow-sm">
                      {agent.label}
                    </div>
                  </div>
                ))}

                <div className="pointer-events-none absolute inset-0 bg-[linear-gradient(145deg,rgba(255,255,255,0.18),transparent_45%,rgba(20,20,19,0.04))]" />
                <div className="absolute bottom-3 left-3 flex flex-wrap gap-2">
                  <span className="border border-[#d8d3c7] bg-white/90 px-2 py-1 font-mono text-[11px] text-[#5f5b52]">
                    {t("source.marker")} {shortValue(scene?.source.deploy_readback_marker)}
                  </span>
                  <span
                    data-testid="openclaw-animation-loop"
                    className={cn(
                      "border px-2 py-1 font-mono text-[11px]",
                      animationLoopEnabled
                        ? "border-[#8fc29a] bg-[#f0faf2] text-[#17602a]"
                        : "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]",
                    )}
                  >
                    {t("animation.loop")}{" "}
                    {animationLoopEnabled ? t("animation.on") : t("animation.off")} ·{" "}
                    {scene?.room.animation_loop.tick_ms ?? 0}ms
                  </span>
                  <span className="border border-[#d8d3c7] bg-white/90 px-2 py-1 font-mono text-[11px] text-[#5f5b52]">
                    {t("source.updated")}{" "}
                    {updatedAt
                      ? updatedAt.toLocaleTimeString(locale, {
                          hour: "2-digit",
                          minute: "2-digit",
                          second: "2-digit",
                        })
                      : "--"}
                  </span>
                </div>
              </div>
            </div>

            <aside className="grid min-w-0 gap-3">
              <section className="border border-[#d8d3c7] bg-white p-4">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-base font-semibold text-[#141413]">
                    {t("panels.rollups")}
                  </h2>
                  <Activity className="h-4 w-4 text-[#4a90d9]" aria-hidden="true" />
                </div>
                <div className="mt-4 grid grid-cols-1 gap-2 sm:grid-cols-2">
                  {[
                    ["agents", scene?.rollups.agent_count],
                    ["workItems", scene?.rollups.work_item_count],
                    ["animated", scene?.rollups.animated_entity_count],
                    ["blocked", scene?.rollups.blocked_work_item_count],
                  ].map(([key, value]) => (
                    <div key={String(key)} className="border border-[#e5e1d8] bg-[#fafafa] p-3">
                      <p className="text-[11px] font-semibold text-[#77736a]">
                        {t(`metrics.${key}`)}
                      </p>
                      <p className="mt-1 font-mono text-2xl font-semibold text-[#141413]">
                        {formatNumber(Number(value ?? 0))}
                      </p>
                    </div>
                  ))}
                </div>
              </section>

              <section className="border border-[#d8d3c7] bg-white p-4">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-base font-semibold text-[#141413]">
                    {t("panels.boundaries")}
                  </h2>
                  <ShieldCheck
                    className={cn("h-4 w-4", boundaryOk ? "text-[#17602a]" : "text-[#8a5a08]")}
                    aria-hidden="true"
                  />
                </div>
                <div className="mt-3 grid gap-2">
                  {[
                    "raw_session_read_allowed",
                    "sqlite_read_allowed",
                    "secret_value_display_allowed",
                    "runtime_action_performed",
                    "host_or_k8s_write_performed",
                  ].map((key) => (
                    <div
                      key={key}
                      className="flex min-w-0 items-center justify-between gap-3 border border-[#e5e1d8] px-3 py-2"
                    >
                      <span className="truncate font-mono text-[11px] text-[#5f5b52]">
                        {key}
                      </span>
                      <span
                        className={cn(
                          "border px-2 py-0.5 text-[10px] font-semibold",
                          scene?.boundaries[key] === false
                            ? "border-[#8fc29a] bg-[#f0faf2] text-[#17602a]"
                            : "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]",
                        )}
                      >
                        {scene?.boundaries[key] === false ? t("boundary.closed") : t("boundary.open")}
                      </span>
                    </div>
                  ))}
                </div>
              </section>

              <section className="min-h-[260px] border border-[#d8d3c7] bg-white p-4">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-base font-semibold text-[#141413]">
                    {t("panels.workItems")}
                  </h2>
                  <SearchCheck className="h-4 w-4 text-[#4a90d9]" aria-hidden="true" />
                </div>
                <div className="mt-3 grid gap-2">
                  {workItems.length === 0 ? (
                    <div className="border border-[#e5e1d8] bg-[#fafafa] p-4 text-sm text-[#77736a]">
                      {t("empty")}
                    </div>
                  ) : (
                    workItems.slice(0, 6).map((item) => (
                      <div key={item.work_item_id} className="border border-[#e5e1d8] p-3">
                        <div className="flex min-w-0 items-center justify-between gap-2">
                          <span className="min-w-0 truncate text-sm font-semibold text-[#141413]">
                            {item.title || item.work_item_id}
                          </span>
                          <span
                            className={cn(
                              "shrink-0 border px-2 py-0.5 text-[10px] font-semibold",
                              stateClass(stateFromWorkItemStatus(item.status)),
                            )}
                          >
                            {stateLabel(t, stateFromWorkItemStatus(item.status))}
                          </span>
                        </div>
                        <p className="mt-2 truncate font-mono text-[11px] text-[#77736a]">
                          {item.next_controlled_action || item.exit_criteria || "--"}
                        </p>
                      </div>
                    ))
                  )}
                </div>
              </section>
            </aside>
          </section>
        </div>
      </main>
      <style jsx global>{`
        @keyframes openclaw-agent-drift {
          0%,
          100% {
            transform: translate(-50%, -50%) translate3d(0, 0, 0);
          }
          50% {
            transform: translate(-50%, -50%) translate3d(5px, -7px, 0);
          }
        }
        @keyframes openclaw-work-token-flow {
          0%,
          100% {
            transform: translate(-50%, -50%) translate3d(0, 0, 0);
          }
          50% {
            transform: translate(-50%, -50%) translate3d(9px, 4px, 0);
          }
        }
        .openclaw-agent {
          animation: openclaw-agent-drift 4.8s ease-in-out infinite;
          will-change: transform;
        }
        .openclaw-work-token {
          animation: openclaw-work-token-flow 6.2s ease-in-out infinite;
          will-change: transform;
        }
        @keyframes openclaw-flow-packet {
          0% {
            transform: translate3d(-8px, 10px, 0) scale(0.76);
            opacity: 0;
          }
          18% {
            opacity: 1;
          }
          50% {
            transform: translate3d(22px, -14px, 0) scale(1);
            opacity: 0.86;
          }
          100% {
            transform: translate3d(48px, -28px, 0) scale(0.72);
            opacity: 0;
          }
        }
        @keyframes openclaw-screen-sweep {
          0% {
            transform: translateX(-100%);
            opacity: 0;
          }
          30% {
            opacity: 0.42;
          }
          100% {
            transform: translateX(160%);
            opacity: 0;
          }
        }
        .openclaw-flow-packet {
          animation: openclaw-flow-packet 5.8s ease-in-out infinite;
          will-change: transform, opacity;
        }
        .openclaw-screen-sweep {
          background: linear-gradient(
            90deg,
            transparent,
            rgba(112, 214, 164, 0.3),
            transparent
          );
          animation: openclaw-screen-sweep 3.8s linear infinite;
          will-change: transform, opacity;
        }
        @media (prefers-reduced-motion: reduce) {
          .openclaw-agent,
          .openclaw-work-token,
          .openclaw-flow-packet,
          .openclaw-screen-sweep {
            animation: none;
          }
        }
      `}</style>
    </AppLayout>
  );
}
