"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { readBackendUnavailableMessage, useResolvedApiBase } from "../lib/api-base";
import { DetailKeyGrid, DetailSection } from "./admin-detail";
import { EmptyPanel, ErrorBanner, NoticeBanner, PageStatus } from "./admin-feedback";
import { AdminFrame } from "./admin-frame";
import { ResourceToolbar } from "./admin-resource";
import styles from "./platform-shell.module.css";

type IncidentSeverity = "info" | "warning" | "major" | "critical";
type IncidentStatus = "open" | "acknowledged" | "resolved";

type IncidentItem = {
  id: string;
  serviceKey: string;
  title: string;
  severity: IncidentSeverity;
  status: IncidentStatus;
  summary: string;
  categoryKey: string;
  rootCategory: string;
  latestTargetId: string | null;
  latestRunId: string | null;
  firstDetectedAt: string;
  lastDetectedAt: string;
  occurrenceCount: number;
  stormScore: number;
  evidence: Record<string, unknown>;
  diagnosis: Record<string, unknown>;
  recommendation: { actions?: string[] };
  sourceSummary: {
    latestRun?: {
      status?: string | null;
      errorTag?: string | null;
      traceId?: string | null;
    } | null;
    alerts?: Array<{ id: string; category: string; severity: string; status: string }>;
  };
};

type IncidentDetail = {
  incident: IncidentItem;
  detail: {
    targets: Array<{ id: string; name: string; type: string; endpoint: string }>;
    alerts: Array<{ id: string; title: string; category: string; severity: string; status: string; summary: string }>;
    recentRuns: Array<{
      id: string;
      traceId: string;
      status: string;
      errorTag: string | null;
      summary: string | null;
      failureReason: string | null;
      startedAt: string;
      target?: { id: string; name: string };
    }>;
    recentLogs: Array<{ id: string; level: string | null; messageText: string; eventAt: string; host: string | null }>;
  };
};

function formatTime(value?: string | null) {
  return value ? new Date(value).toLocaleString("zh-CN", { hour12: false }) : "N/A";
}

function severityLabel(value: IncidentSeverity) {
  return ({ info: "Info", warning: "Warn", major: "Major", critical: "Critical" } as const)[value];
}

function incidentStatusLabel(value: IncidentStatus) {
  return ({ open: "Open", acknowledged: "Ack", resolved: "Resolved" } as const)[value];
}

function readErrorMessage(error: unknown, apiBase?: string) {
  if (error instanceof TypeError) return readBackendUnavailableMessage(apiBase);
  if (error instanceof Error) return error.message;
  if (error && typeof error === "object" && "message" in error) {
    const message = (error as { message?: string | string[] }).message;
    return Array.isArray(message) ? message.join("; ") : (message ?? "Request failed.");
  }
  return "Request failed.";
}

function stringifyJson(value: unknown) {
  return JSON.stringify(value, null, 2);
}

export function IncidentsConsole() {
  const apiBase = useResolvedApiBase();
  const [items, setItems] = useState<IncidentItem[]>([]);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [selectedDetail, setSelectedDetail] = useState<IncidentDetail | null>(null);
  const [statusFilter, setStatusFilter] = useState<"" | IncidentStatus>("open");
  const [severityFilter, setSeverityFilter] = useState<"" | IncidentSeverity>("");
  const [keyword, setKeyword] = useState("");
  const [refreshing, setRefreshing] = useState(false);
  const [errorMessage, setErrorMessage] = useState("");
  const [infoMessage, setInfoMessage] = useState("");
  const [busyKey, setBusyKey] = useState<string | null>(null);

  async function request<T>(path: string, init?: RequestInit) {
    try {
      const response = await fetch(`${apiBase}${path}`, {
        ...init,
        headers: {
          "Content-Type": "application/json",
          ...(init?.headers ?? {}),
        },
        cache: "no-store",
      });
      if (!response.ok) {
        let payload: unknown = null;
        try {
          payload = await response.json();
        } catch {
          payload = null;
        }
        throw new Error(readErrorMessage(payload, apiBase));
      }
      return (await response.json()) as T;
    } catch (error) {
      throw new Error(readErrorMessage(error, apiBase));
    }
  }

  async function loadDetail(id: string) {
    const detail = await request<IncidentDetail>(`/api/incidents/${id}`);
    setSelectedId(id);
    setSelectedDetail(detail);
  }

  async function refreshData(preferredId?: string) {
    setRefreshing(true);
    setErrorMessage("");
    try {
      const params = new URLSearchParams();
      if (statusFilter) params.set("status", statusFilter);
      if (severityFilter) params.set("severity", severityFilter);
      params.set("limit", "100");
      const payload = await request<{ list: IncidentItem[] }>(`/api/incidents?${params.toString()}`);
      setItems(payload.list);
      const nextId = preferredId ?? (selectedId && payload.list.some((item) => item.id === selectedId) ? selectedId : payload.list[0]?.id ?? null);
      if (nextId) {
        await loadDetail(nextId);
      } else {
        setSelectedId(null);
        setSelectedDetail(null);
      }
    } catch (error) {
      setErrorMessage(readErrorMessage(error, apiBase));
    } finally {
      setRefreshing(false);
    }
  }

  useEffect(() => {
    void refreshData();
  }, [apiBase, statusFilter, severityFilter]);

  useEffect(() => {
    if (!infoMessage) return;
    const timer = window.setTimeout(() => setInfoMessage(""), 4000);
    return () => window.clearTimeout(timer);
  }, [infoMessage]);

  const visibleItems = useMemo(() => {
    const q = keyword.trim();
    return items.filter((item) => !q || item.title.includes(q) || item.serviceKey.includes(q) || item.summary.includes(q) || item.categoryKey.includes(q));
  }, [items, keyword]);

  const stats = useMemo(
    () => ({
      total: items.length,
      open: items.filter((item) => item.status === "open").length,
      critical: items.filter((item) => item.severity === "critical").length,
      storming: items.filter((item) => item.stormScore >= 8).length,
    }),
    [items],
  );

  async function handleRebuild() {
    setBusyKey("rebuild");
    try {
      const result = await request<{ incidentCount: number }>("/api/incidents/actions/rebuild", { method: "POST" });
      setInfoMessage(`Rebuilt incidents from current data. Total: ${result.incidentCount}.`);
      await refreshData();
    } catch (error) {
      setErrorMessage(readErrorMessage(error, apiBase));
    } finally {
      setBusyKey(null);
    }
  }

  async function handleUpdateStatus(id: string, status: IncidentStatus) {
    setBusyKey(`${id}:${status}`);
    try {
      await request(`/api/incidents/${id}/status`, {
        method: "PATCH",
        body: JSON.stringify({ status }),
      });
      setInfoMessage(`Incident status updated to ${status}.`);
      await refreshData(id);
    } catch (error) {
      setErrorMessage(readErrorMessage(error, apiBase));
    } finally {
      setBusyKey(null);
    }
  }

  return (
    <AdminFrame
      section="incidents"
      title="Incident Aggregation"
      description="Merge runs, alerts, logs, and evidence into one trackable incident object."
      actions={<PageStatus busy={refreshing} busyLabel="Syncing" idleLabel="Ready" />}
    >
      <NoticeBanner message={infoMessage} />
      <ErrorBanner message={errorMessage} />

      <section className={styles.panel}>
        <div className={styles.pageHeader}>
          <div>
            <p className={styles.pageKicker}>Aggregation</p>
            <h2>Incident overview</h2>
          </div>
          <div className={styles.buttonRow}>
            <button className={styles.secondaryButton} disabled={busyKey === "rebuild"} onClick={() => void handleRebuild()} type="button">
              {busyKey === "rebuild" ? "Rebuilding..." : "Rebuild from current data"}
            </button>
            <button className={styles.secondaryButton} onClick={() => void refreshData()} type="button">
              Refresh
            </button>
          </div>
        </div>
        <div className={styles.statsGrid}>
          <article className={styles.statCard}><span>Total</span><strong>{stats.total}</strong></article>
          <article className={styles.statCard} data-tone="danger"><span>Open</span><strong>{stats.open}</strong></article>
          <article className={styles.statCard} data-tone="danger"><span>Critical</span><strong>{stats.critical}</strong></article>
          <article className={styles.statCard} data-tone="warning"><span>Storm ge 8</span><strong>{stats.storming}</strong></article>
        </div>
      </section>

      <section className={styles.runWorkspace}>
        <section className={styles.runListPanel}>
          <ResourceToolbar title="Incident list" description="Grouped by service and category, then split by time window.">
            <label className={styles.inlineField}>
              <span>Keyword</span>
              <input value={keyword} onChange={(event) => setKeyword(event.target.value)} placeholder="title / service / category" />
            </label>
            <label className={styles.inlineField}>
              <span>Status</span>
              <select value={statusFilter} onChange={(event) => setStatusFilter(event.target.value as "" | IncidentStatus)}>
                <option value="">All</option>
                <option value="open">Open</option>
                <option value="acknowledged">Ack</option>
                <option value="resolved">Resolved</option>
              </select>
            </label>
            <label className={styles.inlineField}>
              <span>Severity</span>
              <select value={severityFilter} onChange={(event) => setSeverityFilter(event.target.value as "" | IncidentSeverity)}>
                <option value="">All</option>
                <option value="critical">Critical</option>
                <option value="major">Major</option>
                <option value="warning">Warning</option>
                <option value="info">Info</option>
              </select>
            </label>
          </ResourceToolbar>

          <div className={styles.runList}>
            {visibleItems.length ? visibleItems.map((item) => (
              <article className={styles.runRow} data-active={selectedId === item.id} key={item.id}>
                <button className={styles.runRowButton} onClick={() => void loadDetail(item.id)} type="button">
                  <div className={styles.runRowMain}>
                    <div className={styles.runRowHeader}>
                      <strong>{item.title}</strong>
                      <span className={styles.badge} data-status={item.severity === "critical" || item.severity === "major" ? "failed" : item.severity === "warning" ? "partial" : "success"}>
                        {severityLabel(item.severity)}
                      </span>
                    </div>
                    <span className={styles.runMetaLine}>
                      <span>{incidentStatusLabel(item.status)}</span>
                      <span>{item.serviceKey}</span>
                      <span>{item.categoryKey}</span>
                      <span>{formatTime(item.lastDetectedAt)}</span>
                    </span>
                    <span>{item.summary}</span>
                  </div>
                  <div className={styles.runRowSide}>
                    <span>{item.occurrenceCount} hits</span>
                    <span>storm {item.stormScore}</span>
                    <span>{item.sourceSummary?.alerts?.length ?? 0} alerts</span>
                  </div>
                </button>
              </article>
            )) : <EmptyPanel message="No incidents matched the current filters." />}
          </div>
        </section>

        <section className={styles.runDetailPanel}>
          {selectedDetail ? (
            <div className={styles.sectionStack}>
              <DetailSection title="Conclusion" description="Current incident state, scope, and aggregation tags.">
                <DetailKeyGrid items={[
                  { label: "title", value: selectedDetail.incident.title },
                  { label: "service_key", value: selectedDetail.incident.serviceKey },
                  { label: "root", value: selectedDetail.incident.rootCategory },
                  { label: "category", value: selectedDetail.incident.categoryKey },
                  { label: "status", value: incidentStatusLabel(selectedDetail.incident.status) },
                  { label: "severity", value: severityLabel(selectedDetail.incident.severity) },
                  { label: "first_seen", value: formatTime(selectedDetail.incident.firstDetectedAt) },
                  { label: "last_seen", value: formatTime(selectedDetail.incident.lastDetectedAt) },
                  { label: "occurrences", value: selectedDetail.incident.occurrenceCount },
                  { label: "storm", value: selectedDetail.incident.stormScore },
                  { label: "latest_run", value: selectedDetail.incident.latestRunId ?? "N/A" },
                ]} />
                <p className={styles.detailDescription}>{selectedDetail.incident.summary}</p>
                <div className={styles.buttonRow}>
                  <button disabled={busyKey === `${selectedDetail.incident.id}:acknowledged`} onClick={() => void handleUpdateStatus(selectedDetail.incident.id, "acknowledged")} type="button">Acknowledge</button>
                  <button className={styles.secondaryButton} disabled={busyKey === `${selectedDetail.incident.id}:open`} onClick={() => void handleUpdateStatus(selectedDetail.incident.id, "open")} type="button">Reopen</button>
                  <button className={styles.secondaryButton} disabled={busyKey === `${selectedDetail.incident.id}:resolved`} onClick={() => void handleUpdateStatus(selectedDetail.incident.id, "resolved")} type="button">Resolve</button>
                </div>
              </DetailSection>

              <DetailSection title="Recommended actions" description="What to check first before drilling into raw evidence.">
                {selectedDetail.incident.recommendation?.actions?.length ? (
                  <ul className={styles.guideList}>
                    {selectedDetail.incident.recommendation.actions.map((action) => (
                      <li key={action}>{action}</li>
                    ))}
                  </ul>
                ) : <EmptyPanel message="No recommended actions yet." />}
              </DetailSection>

              <DetailSection title="Linked objects" description="Targets, alerts, runs, and logs currently attached to this incident.">
                <DetailKeyGrid items={[
                  { label: "targets", value: selectedDetail.detail.targets.length },
                  { label: "alerts", value: selectedDetail.detail.alerts.length },
                  { label: "recent_runs", value: selectedDetail.detail.recentRuns.length },
                  { label: "recent_logs", value: selectedDetail.detail.recentLogs.length },
                ]} />
                <div className={styles.metaChipList}>
                  {selectedDetail.detail.targets.slice(0, 6).map((target) => (
                    <Link className={styles.metaChip} href="/monitors" key={target.id}>
                      {target.name} / {target.type}
                    </Link>
                  ))}
                  {!selectedDetail.detail.targets.length ? <EmptyPanel message="No linked targets." /> : null}
                </div>
              </DetailSection>

              <DetailSection title="Recent alerts" description="Recent alert slices under the same incident bucket.">
                {selectedDetail.detail.alerts.length ? (
                  <div className={styles.metaChipList}>
                    {selectedDetail.detail.alerts.map((alert) => (
                      <span className={styles.metaChip} key={alert.id}>
                        {alert.category} / {alert.severity} / {alert.status}
                      </span>
                    ))}
                  </div>
                ) : <EmptyPanel message="No recent alerts." />}
              </DetailSection>

              <DetailSection title="Recent runs" description="Latest execution records near this incident window.">
                {selectedDetail.detail.recentRuns.length ? (
                  <div className={styles.sectionStack}>
                    {selectedDetail.detail.recentRuns.map((run) => (
                      <article className={styles.detailCard} key={run.id}>
                        <DetailKeyGrid items={[
                          { label: "run", value: run.id },
                          { label: "trace", value: run.traceId },
                          { label: "status", value: run.status },
                          { label: "error_tag", value: run.errorTag ?? "N/A" },
                          { label: "started_at", value: formatTime(run.startedAt) },
                          { label: "target", value: run.target?.name ?? "N/A" },
                        ]} />
                        <p className={styles.detailDescription}>{run.summary ?? run.failureReason ?? "No run summary."}</p>
                      </article>
                    ))}
                  </div>
                ) : <EmptyPanel message="No recent runs." />}
              </DetailSection>

              <DetailSection title="Evidence" description="Raw evidence summary carried by the incident object.">
                <pre className={styles.codeBlock}>{stringifyJson(selectedDetail.incident.evidence)}</pre>
              </DetailSection>

              <DetailSection title="Diagnosis" description="Current diagnosis summary and source metadata.">
                <pre className={styles.codeBlock}>{stringifyJson(selectedDetail.incident.diagnosis)}</pre>
              </DetailSection>
            </div>
          ) : (
            <EmptyPanel message="Select an incident to inspect details." />
          )}
        </section>
      </section>
    </AdminFrame>
  );
}
