import { useEffect, useMemo, useState } from "react";
import {
  Button,
  GlassSurface,
  StatusBadge,
} from "@nodedc/ui-react";

import {
  fetchPolygonRunCatalog,
  fetchPolygonRunDetail,
  type PolygonRunCatalog,
  type PolygonRunDetail,
  type PolygonRunRoute,
  type PolygonRunState,
} from "../core/polygon/runArchive";

interface PolygonRunWorkspaceProps {
  route: PolygonRunRoute;
}

const stateLabels: Record<PolygonRunState, string> = {
  admitted: "Допущен",
  starting: "Запускается",
  running: "Выполняется",
  paused: "На паузе",
  stopping: "Останавливается",
  completed: "Завершён",
  failed: "Ошибка",
  aborted: "Прерван",
};

function stateTone(
  state: PolygonRunState,
): "success" | "accent" | "warning" | "danger" | "neutral" {
  if (state === "completed") return "success";
  if (state === "running") return "accent";
  if (state === "failed" || state === "aborted") return "danger";
  if (state === "starting" || state === "stopping" || state === "paused") return "warning";
  return "neutral";
}

function formatTimestamp(value: string | null): string {
  if (!value) return "—";
  return new Intl.DateTimeFormat("ru-RU", {
    dateStyle: "medium",
    timeStyle: "medium",
  }).format(new Date(value));
}

function formatBytes(value: number): string {
  if (value === 0) return "0 Б";
  const units = ["Б", "КБ", "МБ", "ГБ"];
  const exponent = Math.min(Math.floor(Math.log(value) / Math.log(1024)), units.length - 1);
  return `${(value / 1024 ** exponent).toLocaleString("ru-RU", {
    maximumFractionDigits: 1,
  })} ${units[exponent]}`;
}

function errorMessage(error: unknown): string {
  if (error instanceof Error && error.message.trim()) return error.message;
  return "Не удалось прочитать доказательства прогона.";
}

export function PolygonRunWorkspace({ route }: PolygonRunWorkspaceProps) {
  const [catalog, setCatalog] = useState<PolygonRunCatalog | null>(null);
  const [detail, setDetail] = useState<PolygonRunDetail | null>(null);
  const [selectedRunId, setSelectedRunId] = useState<string | null>(route.runId);
  const [loading, setLoading] = useState(route.error === null);
  const [error, setError] = useState<string | null>(route.error);
  const [reloadGeneration, setReloadGeneration] = useState(0);

  useEffect(() => {
    if (route.error) {
      setLoading(false);
      setError(route.error);
      return;
    }
    const controller = new AbortController();
    setLoading(true);
    setError(null);
    void (async () => {
      try {
        const nextCatalog = await fetchPolygonRunCatalog({ signal: controller.signal });
        if (controller.signal.aborted) return;
        setCatalog(nextCatalog);
        const targetRunId = selectedRunId ?? route.runId ?? nextCatalog.items[0]?.runId ?? null;
        if (!targetRunId) {
          setDetail(null);
          return;
        }
        const nextDetail = await fetchPolygonRunDetail(targetRunId, {
          signal: controller.signal,
        });
        if (controller.signal.aborted) return;
        setSelectedRunId(targetRunId);
        setDetail(nextDetail);
      } catch (loadError) {
        if (controller.signal.aborted) return;
        setDetail(null);
        setError(errorMessage(loadError));
      } finally {
        if (!controller.signal.aborted) setLoading(false);
      }
    })();
    return () => controller.abort();
  }, [reloadGeneration, route.error, route.runId, selectedRunId]);

  const visibleEvents = useMemo(
    () => detail ? [...detail.events].reverse() : [],
    [detail],
  );

  if (loading && !detail) {
    return (
      <div className="standard-workspace polygon-run-workspace">
        <GlassSurface className="polygon-run-message" padding="lg">
          <StatusBadge tone="accent">Только чтение</StatusBadge>
          <h2>Проверяем журнал прогона</h2>
          <p>Mission Core читает манифест, события и индекс артефактов без запуска провайдеров.</p>
        </GlassSurface>
      </div>
    );
  }

  if (error) {
    return (
      <div className="standard-workspace polygon-run-workspace">
        <GlassSurface className="polygon-run-message" padding="lg">
          <StatusBadge tone="danger">Данные недоступны</StatusBadge>
          <h2>UI-0 не может открыть прогон</h2>
          <p>{error}</p>
          <Button
            size="compact"
            variant="secondary"
            onClick={() => setReloadGeneration((value) => value + 1)}
          >
            Повторить чтение
          </Button>
        </GlassSurface>
      </div>
    );
  }

  if (!detail) {
    return (
      <div className="standard-workspace polygon-run-workspace">
        <GlassSurface className="polygon-run-message" padding="lg">
          <StatusBadge tone="neutral">Журнал пуст</StatusBadge>
          <h2>Квалификационных прогонов пока нет</h2>
          <p>Экран появится автоматически после публикации первого журнала в read-only источник.</p>
        </GlassSurface>
      </div>
    );
  }

  const { run } = detail;
  return (
    <div className="standard-workspace polygon-run-workspace">
      <section className="workspace-lead workspace-lead--compact">
        <div>
          <span className="section-eyebrow">ПОЛИГОН / КВАЛИФИКАЦИОННЫЙ ПРОГОН</span>
          <h2>{run.runId}</h2>
          <p>
            Канонический журнал Mission Core. Экран не содержит lifecycle-операций,
            команд управления или доступа к физическим актуаторам.
          </p>
        </div>
        <div className="polygon-run-lead-status">
          <StatusBadge tone={stateTone(run.state)}>{stateLabels[run.state]}</StatusBadge>
          <span>read-only · {run.reproducibilityTier}</span>
        </div>
      </section>

      <section className="polygon-run-metrics" aria-label="Сводка прогона">
        <div>
          <span>Состояние</span>
          <strong>{stateLabels[run.state]}</strong>
          <small>{run.terminalReason ?? "терминальная причина отсутствует"}</small>
        </div>
        <div>
          <span>Провайдеры</span>
          <strong>{run.providers.length}</strong>
          <small>{run.providerIds.join(" · ")}</small>
        </div>
        <div>
          <span>События</span>
          <strong>{detail.eventsTotal}</strong>
          <small>{detail.eventsTruncated ? "показан последний фрагмент" : "журнал целиком"}</small>
        </div>
        <div>
          <span>Команды</span>
          <strong>{detail.commandCount}</strong>
          <small>содержимое не публикуется UI-0</small>
        </div>
      </section>

      <div className="polygon-run-layout">
        <GlassSurface className="polygon-run-catalog" padding="lg">
          <header className="polygon-run-panel-heading">
            <div>
              <span className="section-eyebrow">ПОСЛЕДНИЕ ПРОГОНЫ</span>
              <h3>{catalog?.total ?? 0} в источнике</h3>
            </div>
            <Button
              size="compact"
              variant="secondary"
              onClick={() => setReloadGeneration((value) => value + 1)}
            >
              Обновить
            </Button>
          </header>
          <div className="polygon-run-list">
            {catalog?.items.map((item) => (
              <button
                type="button"
                key={item.runId}
                data-active={item.runId === run.runId ? "true" : undefined}
                onClick={() => setSelectedRunId(item.runId)}
              >
                <i data-state={item.state} aria-hidden="true" />
                <span>
                  <strong>{item.runId}</strong>
                  <small>{formatTimestamp(item.createdAtUtc)}</small>
                </span>
                <em>{stateLabels[item.state]}</em>
              </button>
            ))}
          </div>
        </GlassSurface>

        <GlassSurface className="polygon-run-identity" padding="lg">
          <span className="section-eyebrow">ИДЕНТИЧНОСТЬ И ГРАНИЦА</span>
          <dl>
            <div><dt>Сценарий</dt><dd>{run.scenarioGeneration}</dd></div>
            <div><dt>Профиль</dt><dd>{run.profileGeneration}</dd></div>
            <div><dt>Host profile</dt><dd>{run.hostProfileId}</dd></div>
            <div><dt>Mission Core</dt><dd><code>{run.missionCoreCommit.slice(0, 12)}</code></dd></div>
            <div><dt>Clock</dt><dd><code>{run.clockDomain}</code></dd></div>
            <div><dt>Seed</dt><dd>{run.seed}</dd></div>
            <div><dt>Начало</dt><dd>{formatTimestamp(run.startedAtUtc)}</dd></div>
            <div><dt>Завершение</dt><dd>{formatTimestamp(run.endedAtUtc)}</dd></div>
          </dl>
          <div className="polygon-run-safety-boundary">
            <StatusBadge tone="success">Virtual only</StatusBadge>
            <p>
              Actuator authority: {run.authority.actuatorAuthority ? "да" : "нет"} ·
              direct setpoints: {run.authority.directActuatorSetpointsAllowed ? "да" : "нет"} ·
              navigation/safety accepted: {run.authority.navigationOrSafetyAccepted ? "да" : "нет"}
            </p>
          </div>
        </GlassSurface>
      </div>

      <section className="polygon-run-providers" aria-label="Провайдеры прогона">
        {run.providers.map((provider) => (
          <div key={provider.identifier}>
            <i aria-hidden="true" />
            <span>
              <strong>{provider.identifier}</strong>
              <small>{provider.version}</small>
            </span>
            <code>{provider.revision.slice(0, 16)}</code>
          </div>
        ))}
      </section>

      <GlassSurface className="polygon-run-events" padding="lg">
        <header className="polygon-run-panel-heading">
          <div>
            <span className="section-eyebrow">ЖУРНАЛ СОБЫТИЙ</span>
            <h3>Последние переходы и факты</h3>
          </div>
          <span>revision {run.revision}</span>
        </header>
        <div className="polygon-run-event-list">
          {visibleEvents.map((event) => (
            <article key={event.sequence}>
              <span className="polygon-run-event-sequence">
                {String(event.sequence).padStart(3, "0")}
              </span>
              <div>
                <strong>{event.eventType}</strong>
                <small>{formatTimestamp(event.observedAtUtc)}</small>
                <code>{JSON.stringify(event.payload)}</code>
              </div>
              <span>{event.simTimeNs === null ? "host" : `${event.simTimeNs} ns`}</span>
            </article>
          ))}
        </div>
      </GlassSurface>

      <div className="polygon-run-evidence-grid">
        <GlassSurface className="polygon-run-artifacts" padding="lg">
          <span className="section-eyebrow">АРТЕФАКТЫ</span>
          <h3>{detail.artifacts.length || run.artifactCount} ссылок в индексе</h3>
          {detail.artifacts.length ? (
            <div>
              {detail.artifacts.map((artifact) => (
                <article key={artifact.artifactId}>
                  <span>
                    <strong>{artifact.kind}</strong>
                    <small>{artifact.relativePath}</small>
                  </span>
                  <code>{artifact.sha256.slice(0, 12)} · {formatBytes(artifact.byteLength)}</code>
                </article>
              ))}
            </div>
          ) : (
            <p>В журнале прогона нет зарегистрированных artifact-index записей.</p>
          )}
        </GlassSurface>
        <GlassSurface className="polygon-run-limitations" padding="lg">
          <span className="section-eyebrow">ЧЕСТНАЯ ГРАНИЦА UI-0</span>
          <h3>Что этот результат ещё не доказывает</h3>
          <ul>
            {detail.limitations.map((limitation) => <li key={limitation}>{limitation}</li>)}
          </ul>
        </GlassSurface>
      </div>
    </div>
  );
}
