"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";

type Heartbeat = {
  ts: string;
  status: string;
  message?: string | null;
  ip?: string | null;
  fwVersion?: string | null;
};

type Kpi = {
  ts: string;
  oee?: number | null;
  availability?: number | null;
  performance?: number | null;
  quality?: number | null;
  workOrderId?: string | null;
  sku?: string | null;
  good?: number | null;
  scrap?: number | null;
  target?: number | null;
  cycleTime?: number | null;
};

type MachineRow = {
  id: string;
  name: string;
  code?: string | null;
  location?: string | null;
  latestHeartbeat: Heartbeat | null;
  latestKpi?: Kpi | null;
};

type EventRow = {
  id: string;
  ts: string;
  topic?: string;
  eventType: string;
  severity: string;
  title: string;
  description?: string | null;
  requiresAck: boolean;
  machineId?: string;
  machineName?: string;
  source: "ingested" | "derived";
};

type CycleRow = {
  ts: string;
  t: number;
  cycleCount: number | null;
  actual: number;
  ideal: number | null;
};

const OFFLINE_MS = 15000;
const EVENT_WINDOW_SEC = 1800;
const MAX_EVENT_MACHINES = 6;
const TOL = 0.10;

function secondsAgo(ts?: string) {
  if (!ts) return "never";
  const diff = Math.floor((Date.now() - new Date(ts).getTime()) / 1000);
  if (diff < 60) return `${diff}s ago`;
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
  return `${Math.floor(diff / 3600)}h ago`;
}

function isOffline(ts?: string) {
  if (!ts) return true;
  return Date.now() - new Date(ts).getTime() > OFFLINE_MS;
}

function fmtPct(v?: number | null) {
  if (v === null || v === undefined || Number.isNaN(v)) return "--";
  return `${v.toFixed(1)}%`;
}

function fmtNum(v?: number | null) {
  if (v === null || v === undefined || Number.isNaN(v)) return "--";
  return `${Math.round(v)}`;
}

function severityClass(sev?: string) {
  const s = (sev ?? "").toLowerCase();
  if (s === "critical") return "bg-red-500/15 text-red-300";
  if (s === "warning") return "bg-yellow-500/15 text-yellow-300";
  if (s === "info") return "bg-blue-500/15 text-blue-300";
  return "bg-white/10 text-zinc-200";
}

function sourceClass(src: EventRow["source"]) {
  return src === "ingested"
    ? "bg-white/10 text-zinc-200"
    : "bg-emerald-500/15 text-emerald-300";
}

function classifyDerivedEvent(c: CycleRow) {
  if (c.ideal == null || c.ideal <= 0 || c.actual <= 0) return null;
  if (c.actual <= c.ideal * (1 + TOL)) return null;
  const extra = c.actual - c.ideal;
  let eventType = "slow-cycle";
  let severity = "warning";
  if (extra <= 1) {
    eventType = "slow-cycle";
    severity = "info";
  } else if (extra <= 10) {
    eventType = "microstop";
    severity = "warning";
  } else {
    eventType = "macrostop";
    severity = "critical";
  }

  return {
    eventType,
    severity,
    title:
      eventType === "macrostop"
        ? "Macrostop Detected"
        : eventType === "microstop"
        ? "Microstop Detected"
        : "Slow Cycle Detected",
    description: `Cycle ${c.actual.toFixed(2)}s (ideal ${c.ideal.toFixed(2)}s)`,
  };
}

export default function OverviewPage() {
  const [machines, setMachines] = useState<MachineRow[]>([]);
  const [events, setEvents] = useState<EventRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [eventsLoading, setEventsLoading] = useState(false);

  useEffect(() => {
    let alive = true;

    async function load() {
      try {
        const res = await fetch("/api/machines", { cache: "no-store" });
        const json = await res.json();
        if (!alive) return;
        setMachines(json.machines ?? []);
        setLoading(false);
      } catch {
        if (!alive) return;
        setLoading(false);
      }
    }

    load();
    const t = setInterval(load, 15000);
    return () => {
      alive = false;
      clearInterval(t);
    };
  }, []);

  useEffect(() => {
    if (!machines.length) {
      setEvents([]);
      return;
    }

    let alive = true;
    const controller = new AbortController();

    async function loadEvents() {
      setEventsLoading(true);

      const sorted = [...machines].sort((a, b) => {
        const at = a.latestHeartbeat?.ts ? new Date(a.latestHeartbeat.ts).getTime() : 0;
        const bt = b.latestHeartbeat?.ts ? new Date(b.latestHeartbeat.ts).getTime() : 0;
        return bt - at;
      });

      const targets = sorted.slice(0, MAX_EVENT_MACHINES);

      try {
        const results = await Promise.all(
          targets.map(async (m) => {
            const res = await fetch(`/api/machines/${m.id}?windowSec=${EVENT_WINDOW_SEC}`, {
              cache: "no-store",
              signal: controller.signal,
            });
            const json = await res.json();
            return { machine: m, payload: json };
          })
        );

        if (!alive) return;

        const combined: EventRow[] = [];
        for (const { machine, payload } of results) {
          const ingested = Array.isArray(payload?.events) ? payload.events : [];
          for (const e of ingested) {
            if (!e?.ts) continue;
            combined.push({
              ...e,
              machineId: machine.id,
              machineName: machine.name,
              source: "ingested",
            });
          }

          const cycles: CycleRow[] = Array.isArray(payload?.cycles) ? payload.cycles : [];
          for (const c of cycles.slice(-120)) {
            const derived = classifyDerivedEvent(c);
            if (!derived) continue;
            combined.push({
              id: `derived-${machine.id}-${c.t}`,
              ts: c.ts,
              topic: derived.eventType,
              eventType: derived.eventType,
              severity: derived.severity,
              title: derived.title,
              description: derived.description,
              requiresAck: false,
              machineId: machine.id,
              machineName: machine.name,
              source: "derived",
            });
          }
        }

        const seen = new Set<string>();
        const deduped = combined.filter((e) => {
          const key = `${e.machineId ?? ""}-${e.eventType}-${e.ts}-${e.title}`;
          if (seen.has(key)) return false;
          seen.add(key);
          return true;
        });

        deduped.sort((a, b) => new Date(b.ts).getTime() - new Date(a.ts).getTime());
        setEvents(deduped.slice(0, 30));
      } catch {
        if (!alive) return;
        setEvents([]);
      } finally {
        if (alive) setEventsLoading(false);
      }
    }

    loadEvents();
    return () => {
      alive = false;
      controller.abort();
    };
  }, [machines]);

  const stats = useMemo(() => {
    const total = machines.length;
    let online = 0;
    let running = 0;
    let idle = 0;
    let stopped = 0;
    let oeeSum = 0;
    let oeeCount = 0;
    let availSum = 0;
    let availCount = 0;
    let perfSum = 0;
    let perfCount = 0;
    let qualSum = 0;
    let qualCount = 0;
    let goodSum = 0;
    let scrapSum = 0;
    let targetSum = 0;

    for (const m of machines) {
      const hb = m.latestHeartbeat;
      const offline = isOffline(hb?.ts);
      if (!offline) online += 1;

      const status = (hb?.status ?? "").toUpperCase();
      if (!offline) {
        if (status === "RUN") running += 1;
        else if (status === "IDLE") idle += 1;
        else if (status === "STOP" || status === "DOWN") stopped += 1;
      }

      const k = m.latestKpi;
      if (k?.oee != null) {
        oeeSum += Number(k.oee);
        oeeCount += 1;
      }
      if (k?.availability != null) {
        availSum += Number(k.availability);
        availCount += 1;
      }
      if (k?.performance != null) {
        perfSum += Number(k.performance);
        perfCount += 1;
      }
      if (k?.quality != null) {
        qualSum += Number(k.quality);
        qualCount += 1;
      }
      if (k?.good != null) goodSum += Number(k.good);
      if (k?.scrap != null) scrapSum += Number(k.scrap);
      if (k?.target != null) targetSum += Number(k.target);
    }

    return {
      total,
      online,
      offline: total - online,
      running,
      idle,
      stopped,
      oee: oeeCount ? oeeSum / oeeCount : null,
      availability: availCount ? availSum / availCount : null,
      performance: perfCount ? perfSum / perfCount : null,
      quality: qualCount ? qualSum / qualCount : null,
      goodSum,
      scrapSum,
      targetSum,
    };
  }, [machines]);

  const attention = useMemo(() => {
    const list = machines
      .map((m) => {
        const hb = m.latestHeartbeat;
        const offline = isOffline(hb?.ts);
        const k = m.latestKpi;
        const oee = k?.oee ?? null;
        let score = 0;
        if (offline) score += 100;
        if (oee != null && oee < 75) score += 50;
        if (oee != null && oee < 85) score += 25;
        return { machine: m, offline, oee, score };
      })
      .filter((x) => x.score > 0)
      .sort((a, b) => b.score - a.score)
      .slice(0, 6);

    return list;
  }, [machines]);

  return (
    <div className="p-6">
      <div className="mb-6 flex items-start justify-between gap-4">
        <div>
          <h1 className="text-2xl font-semibold text-white">Overview</h1>
          <p className="text-sm text-zinc-400">Fleet pulse, alerts, and top attention items.</p>
        </div>

        <Link
          href="/machines"
          className="rounded-xl border border-white/10 bg-white/5 px-4 py-2 text-sm text-white hover:bg-white/10"
        >
          View Machines
        </Link>
      </div>

      {loading && <div className="mb-4 text-sm text-zinc-400">Loading overview...</div>}

      <div className="grid grid-cols-1 gap-4 xl:grid-cols-3">
        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">Fleet Health</div>
          <div className="mt-2 text-3xl font-semibold text-white">{stats.total}</div>
          <div className="mt-2 text-xs text-zinc-400">Machines total</div>
          <div className="mt-4 flex flex-wrap gap-2 text-xs">
            <span className="rounded-full bg-emerald-500/15 px-2 py-0.5 text-emerald-300">
              Online {stats.online}
            </span>
            <span className="rounded-full bg-white/10 px-2 py-0.5 text-zinc-300">
              Offline {stats.offline}
            </span>
            <span className="rounded-full bg-emerald-500/10 px-2 py-0.5 text-emerald-200">
              Run {stats.running}
            </span>
            <span className="rounded-full bg-yellow-500/15 px-2 py-0.5 text-yellow-300">
              Idle {stats.idle}
            </span>
            <span className="rounded-full bg-red-500/15 px-2 py-0.5 text-red-300">
              Stop {stats.stopped}
            </span>
          </div>
        </div>

        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">Production Totals</div>
          <div className="mt-2 grid grid-cols-3 gap-3">
            <div className="rounded-xl border border-white/10 bg-black/20 p-3">
              <div className="text-[11px] text-zinc-400">Good</div>
              <div className="mt-1 text-sm font-semibold text-white">{fmtNum(stats.goodSum)}</div>
            </div>
            <div className="rounded-xl border border-white/10 bg-black/20 p-3">
              <div className="text-[11px] text-zinc-400">Scrap</div>
              <div className="mt-1 text-sm font-semibold text-white">{fmtNum(stats.scrapSum)}</div>
            </div>
            <div className="rounded-xl border border-white/10 bg-black/20 p-3">
              <div className="text-[11px] text-zinc-400">Target</div>
              <div className="mt-1 text-sm font-semibold text-white">{fmtNum(stats.targetSum)}</div>
            </div>
          </div>
          <div className="mt-3 text-xs text-zinc-400">Sum of latest KPIs across machines.</div>
        </div>

        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">Activity Feed</div>
          <div className="mt-2 text-3xl font-semibold text-white">{events.length}</div>
          <div className="mt-2 text-xs text-zinc-400">
            {eventsLoading ? "Refreshing recent events..." : "Last 30 merged events"}
          </div>
          <div className="mt-4 space-y-2">
            {events.slice(0, 3).map((e) => (
              <div key={e.id} className="flex items-center justify-between text-xs text-zinc-300">
                <div className="truncate">
                  {e.machineName ? `${e.machineName}: ` : ""}
                  {e.title}
                </div>
                <div className="shrink-0 text-zinc-500">{secondsAgo(e.ts)}</div>
              </div>
            ))}
            {events.length === 0 && !eventsLoading ? (
              <div className="text-xs text-zinc-500">No recent events.</div>
            ) : null}
          </div>
        </div>
      </div>

      <div className="mt-6 grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">OEE (avg)</div>
          <div className="mt-2 text-3xl font-semibold text-emerald-300">{fmtPct(stats.oee)}</div>
        </div>
        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">Availability (avg)</div>
          <div className="mt-2 text-2xl font-semibold text-white">{fmtPct(stats.availability)}</div>
        </div>
        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">Performance (avg)</div>
          <div className="mt-2 text-2xl font-semibold text-white">{fmtPct(stats.performance)}</div>
        </div>
        <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
          <div className="text-xs text-zinc-400">Quality (avg)</div>
          <div className="mt-2 text-2xl font-semibold text-white">{fmtPct(stats.quality)}</div>
        </div>
      </div>

      <div className="mt-6 grid grid-cols-1 gap-4 xl:grid-cols-3">
        <div className="rounded-2xl border border-white/10 bg-white/5 p-5 xl:col-span-1">
          <div className="mb-3 flex items-center justify-between">
            <div className="text-sm font-semibold text-white">Attention List</div>
            <div className="text-xs text-zinc-400">{attention.length} shown</div>
          </div>
          {attention.length === 0 ? (
            <div className="text-sm text-zinc-400">No urgent issues detected.</div>
          ) : (
            <div className="space-y-3">
              {attention.map(({ machine, offline, oee }) => (
                <div key={machine.id} className="rounded-xl border border-white/10 bg-black/20 p-3">
                  <div className="flex items-center justify-between gap-3">
                    <div className="min-w-0">
                      <div className="truncate text-sm font-semibold text-white">{machine.name}</div>
                      <div className="mt-1 text-xs text-zinc-400">
                        {machine.code ?? ""} {machine.location ? `- ${machine.location}` : ""}
                      </div>
                    </div>
                    <div className="text-xs text-zinc-400">{secondsAgo(machine.latestHeartbeat?.ts)}</div>
                  </div>
                  <div className="mt-2 flex items-center gap-2 text-xs">
                    <span
                      className={`rounded-full px-2 py-0.5 ${
                        offline ? "bg-white/10 text-zinc-300" : "bg-emerald-500/15 text-emerald-300"
                      }`}
                    >
                      {offline ? "OFFLINE" : "ONLINE"}
                    </span>
                    {oee != null && (
                      <span className="rounded-full bg-yellow-500/15 px-2 py-0.5 text-yellow-300">
                        OEE {fmtPct(oee)}
                      </span>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="rounded-2xl border border-white/10 bg-white/5 p-5 xl:col-span-2">
          <div className="mb-3 flex items-center justify-between">
            <div className="text-sm font-semibold text-white">Unified Timeline</div>
            <div className="text-xs text-zinc-400">{events.length} items</div>
          </div>

          {events.length === 0 && !eventsLoading ? (
            <div className="text-sm text-zinc-400">No events yet.</div>
          ) : (
            <div className="h-[360px] space-y-3 overflow-y-auto no-scrollbar">
              {events.map((e) => (
                <div key={`${e.id}-${e.source}`} className="rounded-xl border border-white/10 bg-black/20 p-4">
                  <div className="flex items-start justify-between gap-3">
                    <div className="min-w-0">
                      <div className="flex flex-wrap items-center gap-2">
                        <span className={`rounded-full px-2 py-0.5 text-xs ${severityClass(e.severity)}`}>
                          {e.severity.toUpperCase()}
                        </span>
                        <span className="rounded-full bg-white/10 px-2 py-0.5 text-xs text-zinc-200">
                          {e.eventType}
                        </span>
                        <span className={`rounded-full px-2 py-0.5 text-xs ${sourceClass(e.source)}`}>
                          {e.source}
                        </span>
                        {e.requiresAck ? (
                          <span className="rounded-full bg-white/10 px-2 py-0.5 text-xs text-white">ACK</span>
                        ) : null}
                      </div>

                      <div className="mt-2 truncate text-sm font-semibold text-white">
                        {e.machineName ? `${e.machineName}: ` : ""}
                        {e.title}
                      </div>
                      {e.description ? (
                        <div className="mt-1 text-sm text-zinc-300">{e.description}</div>
                      ) : null}
                    </div>
                    <div className="shrink-0 text-xs text-zinc-400">{secondsAgo(e.ts)}</div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
