"use client";

import Image from "next/image";
import {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { ECGMonitorCard } from "@/components/ECGMonitorCard";
import type { PollState } from "@/types/monitor";

interface HealthSummary {
  status: string;
  version?: string;
  serviceId?: string;
  description?: string;
  checks?:
    | Record<string, { status: string; output?: string; details?: string }>
    | {
        name?: string;
        key?: string;
        check?: string;
        status: string;
        output?: string;
        details?: string;
      }[];
}

const POLL_INTERVALS = {
  live: 10_000,
  ready: 30_000,
  health: 60_000,
} as const;

const WAVE_SAMPLES = 140;
const WAVE_WIDTH = 360;
const BASELINE = 68;
const MIN_Y = 20;
const MAX_Y = 110;
const NOISE = 1.4;

function formatTime(timestamp: string | null) {
  if (!timestamp) return "Pending";
  return new Date(timestamp).toLocaleTimeString([], {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  });
}

function useNowString() {
  const [now, setNow] = useState<string>("");

  useEffect(() => {
    const tick = () =>
      setNow(
        new Date().toLocaleTimeString([], {
          hour: "2-digit",
          minute: "2-digit",
          second: "2-digit",
        })
      );

    tick();
    const id = setInterval(tick, 1_000);
    return () => clearInterval(id);
  }, []);

  return now;
}

function hasStatusField(value: unknown): value is { status?: unknown } {
  return typeof value === "object" && value !== null && "status" in value;
}

function isStatusHealthy(value: unknown): boolean {
  if (!value) return false;
  if (typeof value === "string") {
    return ["ok", "pass", "healthy", "up", "ready", "live"].includes(
      value.toLowerCase()
    );
  }
  if (hasStatusField(value) && typeof value.status === "string") {
    return ["ok", "pass", "healthy", "up", "ready", "live"].includes(
      value.status.toLowerCase()
    );
  }
  return false;
}

/**
 * Drives the shared ECG waveform: keeps the line scrolling and injects pulse spikes
 * whenever a poll occurs so the right edge always shows the freshest activity.
 */
function useWaveform() {
  const [wave, setWave] = useState<number[]>(() =>
    Array.from({ length: WAVE_SAMPLES }, () => BASELINE)
  );
  const queueRef = useRef<number[]>([]);
  const tickRef = useRef(0);

  // Queue sharp spikes that get blended into the scrolling ECG line.
  const triggerPulse = useCallback((strength = 18) => {
    queueRef.current.push(
      BASELINE - 6,
      BASELINE + strength,
      BASELINE - 10,
      BASELINE + strength * 0.6
    );
  }, []);

  useEffect(() => {
    const id = setInterval(() => {
      setWave((prev) => {
        const queue = queueRef.current;
        const drift =
          Math.sin(tickRef.current / 6) * NOISE +
          Math.cos(tickRef.current / 9) * (NOISE / 1.6);
        tickRef.current += 1;
        const nextVal = queue.length
          ? queue.shift() ?? BASELINE
          : BASELINE + drift;
        const clamped = Math.max(MIN_Y, Math.min(MAX_Y, nextVal));
        const next = prev.slice(1);
        next.push(clamped);
        return next;
      });
    }, 110);
    return () => clearInterval(id);
  }, []);

  const wavePoints = useMemo(
    () =>
      wave
        .map((value, idx) => {
          const x = (idx / (wave.length - 1)) * WAVE_WIDTH;
          return `${x.toFixed(1)},${value.toFixed(1)}`;
        })
        .join(" "),
    [wave]
  );

  return { wavePoints, waveHeight: wave[wave.length - 1], triggerPulse };
}

/**
 * Polls an endpoint on a cadence, parsing the response and surfacing status metadata.
 */
function usePoller<T>(opts: {
  baseUrl: string;
  path: string;
  intervalMs: number;
  parser: (res: Response) => Promise<T>;
  onPoll?: () => void;
}): { state: PollState<T>; pollNow: () => Promise<void> } {
  const { baseUrl, path, intervalMs, parser, onPoll } = opts;
  const [state, setState] = useState<PollState<T>>({
    data: null,
    error: null,
    loading: false,
    lastUpdated: null,
    attemptedUrl: `${baseUrl}${path}`,
  });

  const poll = useCallback(async () => {
    const url = `${baseUrl}${path}`;
    onPoll?.();
    setState((prev) => ({
      ...prev,
      loading: true,
      attemptedUrl: url,
    }));

    try {
      const res = await fetch(url, { cache: "no-store" });
      if (!res.ok) throw new Error(`${path} responded with ${res.status}`);
      const parsed = await parser(res);
      setState((prev) => ({
        ...prev,
        data: parsed,
        error: null,
        lastUpdated: new Date().toISOString(),
        loading: false,
      }));
    } catch (error) {
      const message = error instanceof Error ? error.message : "Unknown error";
      setState((prev) => ({
        ...prev,
        data: null,
        error: message,
        lastUpdated: new Date().toISOString(),
        loading: false,
      }));
    }
  }, [baseUrl, path, parser, onPoll]);

  useEffect(() => {
    void poll();
    const id = setInterval(() => void poll(), intervalMs);
    return () => clearInterval(id);
  }, [poll, intervalMs]);

  return { state, pollNow: poll };
}

export default function Home() {
  const apiBase = useMemo(
    () => process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000",
    []
  );
  const now = useNowString();
  const unifiedWave = useWaveform();
  const liveWave = useWaveform();
  const readyWave = useWaveform();
  const healthWave = useWaveform();

  const parseHealth = useCallback(async (res: Response) => {
    return (await res.json()) as HealthSummary;
  }, []);
  const parseText = useCallback(async (res: Response) => res.text(), []);

  const pulseHealth = useCallback(() => {
    unifiedWave.triggerPulse(22);
    healthWave.triggerPulse(22);
  }, [unifiedWave.triggerPulse, healthWave.triggerPulse]);
  const pulseReady = useCallback(() => {
    unifiedWave.triggerPulse(16);
    readyWave.triggerPulse(16);
  }, [unifiedWave.triggerPulse, readyWave.triggerPulse]);
  const pulseLive = useCallback(() => {
    unifiedWave.triggerPulse(12);
    liveWave.triggerPulse(12);
  }, [unifiedWave.triggerPulse, liveWave.triggerPulse]);

  const { state: healthState, pollNow: pollHealth } = usePoller<HealthSummary>({
    baseUrl: apiBase,
    path: "/health",
    intervalMs: POLL_INTERVALS.health,
    parser: parseHealth,
    onPoll: pulseHealth,
  });

  const { state: readyState, pollNow: pollReady } = usePoller<string>({
    baseUrl: apiBase,
    path: "/health/ready",
    intervalMs: POLL_INTERVALS.ready,
    parser: parseText,
    onPoll: pulseReady,
  });

  const { state: liveState, pollNow: pollLive } = usePoller<string>({
    baseUrl: apiBase,
    path: "/health/live",
    intervalMs: POLL_INTERVALS.live,
    parser: parseText,
    onPoll: pulseLive,
  });

  const healthOk = isStatusHealthy(healthState.data?.status) && !healthState.error;
  const readyOk = isStatusHealthy(readyState.data) && !readyState.error;
  const liveOk = isStatusHealthy(liveState.data) && !liveState.error;
  const overallOk = healthOk && readyOk && liveOk;

  const checks = useMemo(() => {
    const source = healthState.data?.checks;
    if (!source) return [];
    if (Array.isArray(source)) {
      return source.map((item, idx) => ({
        label: item.name ?? item.key ?? item.check ?? `Check ${idx + 1}`,
        status: item.status ?? "unknown",
        output: item.output ?? item.details ?? "",
      }));
    }
    return Object.entries(source).map(([label, val]) => ({
      label,
      status: (val as { status?: string }).status ?? "unknown",
      output:
        (val as { output?: string; details?: string }).output ??
        (val as { details?: string }).details ??
        "",
    }));
  }, [healthState.data?.checks]);

  const overallLabel = overallOk
    ? "All probes healthy"
    : "Attention needed";
  const overallLoading =
    healthState.loading || readyState.loading || liveState.loading;
  const overallStrokeColor = overallLoading
    ? "var(--color-pulse)"
    : overallOk
      ? "var(--color-success)"
      : "var(--color-danger)";

  return (
    <main className="relative min-h-screen overflow-hidden">
      <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_20%_10%,rgba(148,163,184,0.18),transparent_45%),radial-gradient(circle_at_80%_0%,rgba(203,213,225,0.18),transparent_35%),radial-gradient(circle_at_40%_90%,rgba(226,232,240,0.22),transparent_40%)]" />
      <div className="absolute inset-0 bg-gradient-to-b from-white/80 via-[#f3f4f6cc] to-[#e5e7eb80] backdrop-blur-[1px]" />

      <div className="relative mx-auto flex w-full max-w-6xl flex-col gap-6 px-4 pb-16 pt-10 sm:px-6 lg:px-8">
        <header className="flex flex-col gap-4 rounded-3xl border border-black/5 bg-white/80 px-5 py-4 shadow-card backdrop-blur md:flex-row md:items-center md:justify-between">
          <div className="flex items-center gap-3">
            <div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-black/5 bg-gradient-to-br from-white via-white to-slate-50 shadow-sm">
              <Image
                src="/logo.png"
                alt="avaaz.ai logo"
                width={40}
                height={40}
                priority
                className="h-9 w-9 rounded-xl object-contain"
              />
            </div>
            <div>
              <p className="text-lg font-semibold text-ink">avaaz.ai</p>
              <p className="text-sm text-inkMuted">
                Unified ECG monitoring for live, ready, and health probes.
              </p>
            </div>
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <span
              className={`inline-flex items-center gap-2 rounded-full border px-3 py-2 text-sm font-semibold shadow-sm ${
                overallOk
                  ? "border-emerald-200 bg-emerald-50 text-emerald-800"
                  : "border-rose-200 bg-rose-50 text-rose-800"
              }`}
            >
              <span
                className={`h-2.5 w-2.5 rounded-full ${
                  overallOk ? "bg-success" : "bg-danger"
                }`}
              />
              {overallLabel}
            </span>
            <span className="inline-flex items-center gap-2 rounded-full border border-black/5 bg-black/5 px-3 py-2 text-xs font-semibold uppercase tracking-[0.1em] text-inkMuted">
              Live clock
              <span className="font-mono text-sm">{now || "— — : — —"}</span>
            </span>
          </div>
        </header>

        <section className="grid gap-5 md:grid-cols-[1.1fr,1.4fr]">
          <div className="rounded-3xl border border-black/5 bg-white/80 p-6 shadow-card backdrop-blur">
            <p className="text-xs uppercase tracking-[0.2em] text-inkMuted">
              Live dashboard
            </p>
            <h1 className="mt-2 text-3xl font-semibold leading-tight text-ink md:text-4xl">
              ECG-style observability for avaaz.ai
            </h1>
            <p className="mt-3 text-base text-inkMuted">
              A continuous, scrolling signal shows every poll with sharp blips
              whenever a probe fires. Color shifts between healthy (green),
              unhealthy (red), and active polling (amber).
            </p>
            <div className="mt-4 grid grid-cols-1 gap-3 text-sm text-ink">
              <div className="flex items-center justify-between rounded-2xl border border-black/5 bg-white/70 px-4 py-3">
                <span className="text-inkMuted">/health/live</span>
                <span className="font-semibold">
                  {liveOk ? "Live" : "Down"} · 10s cadence
                </span>
              </div>
              <div className="flex items-center justify-between rounded-2xl border border-black/5 bg-white/70 px-4 py-3">
                <span className="text-inkMuted">/health/ready</span>
                <span className="font-semibold">
                  {readyOk ? "Ready" : "Not ready"} · 30s cadence
                </span>
              </div>
              <div className="flex items-center justify-between rounded-2xl border border-black/5 bg-white/70 px-4 py-3">
                <span className="text-inkMuted">/health</span>
                <span className="font-semibold">
                  {healthOk ? "Healthy" : "Degraded"} · 60s cadence
                </span>
              </div>
            </div>
          </div>

          <div className="relative overflow-hidden rounded-3xl border border-black/5 bg-gradient-to-br from-white via-[#f3f4f6] to-white p-6 shadow-card">
            <div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_20%_10%,rgba(148,163,184,0.18),transparent_35%),radial-gradient(circle_at_80%_10%,rgba(203,213,225,0.14),transparent_30%),radial-gradient(circle_at_40%_90%,rgba(226,232,240,0.14),transparent_28%)]" />
            <div className="flex items-center justify-between text-sm text-inkMuted">
              <span className="font-semibold uppercase tracking-[0.12em]">
                Unified ECG strip
              </span>
              <span className="inline-flex items-center gap-2 rounded-full border border-black/5 bg-white/70 px-3 py-1 font-semibold text-ink">
                <span className="h-2 w-2 rounded-full bg-success" />
                Healthy
                <span className="h-2 w-2 rounded-full bg-danger" />
                Unhealthy
                <span className="h-2 w-2 rounded-full bg-pulse" />
                Polling
              </span>
            </div>
            <div className="mt-3 rounded-2xl border border-black/5 bg-white/80 p-4 shadow-inner">
              <svg
                viewBox="0 0 360 120"
                preserveAspectRatio="none"
                className="h-32 w-full"
              >
                <polyline
                  points={unifiedWave.wavePoints}
                  fill="none"
                  stroke={overallStrokeColor}
                  strokeWidth="4"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                />
                <circle
                  cx="360"
                  cy={unifiedWave.waveHeight}
                  r="7"
                  className="stroke-white/50"
                  style={{ fill: overallStrokeColor }}
                />
              </svg>
            </div>
            <div className="mt-3 grid grid-cols-2 gap-3 text-sm text-ink">
              <div className="rounded-2xl border border-black/5 bg-white/70 px-3 py-2">
                <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                  Last health update
                </p>
                <p className="text-base font-semibold text-ink">
                  {formatTime(healthState.lastUpdated)}
                </p>
              </div>
              <div className="rounded-2xl border border-black/5 bg-white/70 px-3 py-2">
                <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                  Next pulse cadence
                </p>
                <p className="text-base font-semibold text-ink">
                  10s / 30s / 60s
                </p>
              </div>
            </div>
          </div>
        </section>

        <section className="grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3">
          <ECGMonitorCard
            title="Live probe"
            endpoint="/health/live"
            intervalLabel="10 seconds"
            tone="blue"
            now={now}
            wavePoints={liveWave.wavePoints}
            waveHeight={liveWave.waveHeight}
            healthy={liveOk}
            loading={liveState.loading}
            statusLabel={
              liveState.loading
                ? "Polling"
                : liveOk
                  ? "Operational"
                  : "Attention"
            }
            statusDetail={liveState.error ?? liveState.data ?? "Awaiting data"}
            lastUpdatedLabel={formatTime(liveState.lastUpdated)}
            state={liveState}
            onManualTrigger={pollLive}
          >
            <div className="rounded-2xl border border-black/5 bg-white/80 px-3 py-2 text-sm">
              <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                Signal
              </p>
              <p className="font-semibold text-ink">
                {liveState.data ?? liveState.error ?? "No response yet"}
              </p>
            </div>
          </ECGMonitorCard>

          <ECGMonitorCard
            title="Readiness"
            endpoint="/health/ready"
            intervalLabel="30 seconds"
            tone="mint"
            now={now}
            wavePoints={readyWave.wavePoints}
            waveHeight={readyWave.waveHeight}
            healthy={readyOk}
            loading={readyState.loading}
            statusLabel={
              readyState.loading
                ? "Polling"
                : readyOk
                  ? "Operational"
                  : "Attention"
            }
            statusDetail={
              readyState.error ??
              readyState.data ??
              "Waiting for first readiness signal"
            }
            lastUpdatedLabel={formatTime(readyState.lastUpdated)}
            state={readyState}
            onManualTrigger={pollReady}
          >
            <div className="rounded-2xl border border-black/5 bg-white/80 px-3 py-2 text-sm">
              <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                Response
              </p>
              <p className="font-semibold text-ink">
                {readyState.data ?? readyState.error ?? "No response yet"}
              </p>
            </div>
          </ECGMonitorCard>

          <ECGMonitorCard
            title="Deep health"
            endpoint="/health"
            intervalLabel="1 minute"
            tone="coral"
            now={now}
            wavePoints={healthWave.wavePoints}
            waveHeight={healthWave.waveHeight}
            healthy={healthOk}
            loading={healthState.loading}
            statusLabel={
              healthState.loading
                ? "Polling"
                : healthOk
                  ? "Operational"
                  : "Attention"
            }
            statusDetail={
              healthState.error ??
              healthState.data?.status ??
              "Waiting for first health payload"
            }
            lastUpdatedLabel={formatTime(healthState.lastUpdated)}
            state={healthState}
            onManualTrigger={pollHealth}
          >
            <div className="grid grid-cols-2 gap-3 text-sm">
              {healthState.data?.version && (
                <div className="rounded-2xl border border-black/5 bg-white/80 px-3 py-2">
                  <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                    Version
                  </p>
                  <p className="font-semibold text-ink">{healthState.data.version}</p>
                </div>
              )}
              {healthState.data?.serviceId && (
                <div className="rounded-2xl border border-black/5 bg-white/80 px-3 py-2">
                  <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                    Service
                  </p>
                  <p className="font-semibold text-ink">
                    {healthState.data.serviceId}
                  </p>
                </div>
              )}
              {healthState.data?.description && (
                <div className="col-span-2 rounded-2xl border border-black/5 bg-white/80 px-3 py-2">
                  <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                    Notes
                  </p>
                  <p className="text-ink">{healthState.data.description}</p>
                </div>
              )}
            </div>
            <div className="mt-3 space-y-2">
              <p className="text-xs uppercase tracking-[0.08em] text-inkMuted">
                Checks
              </p>
              {checks.length > 0 ? (
                <div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
                  {checks.map((check) => (
                    <div
                      key={check.label}
                      className="rounded-2xl border border-black/5 bg-white/70 px-3 py-2"
                    >
                      <div className="flex items-center justify-between text-xs text-inkMuted">
                        <span>{check.label}</span>
                        <span
                          className={`h-2 w-2 rounded-full ${
                            isStatusHealthy(check.status) ? "bg-success" : "bg-danger"
                          }`}
                        />
                      </div>
                      <p className="text-sm font-semibold text-ink">{check.status}</p>
                      {check.output && (
                        <p className="text-xs text-inkMuted">{check.output}</p>
                      )}
                    </div>
                  ))}
                </div>
              ) : (
                <p className="text-sm text-inkMuted">Awaiting check details.</p>
              )}
            </div>
          </ECGMonitorCard>
        </section>
      </div>
    </main>
  );
}
