import React, { useEffect, useMemo, useRef, useState } from "react";
import { Activity, AlertTriangle, Box, Copy, FileText, RotateCw, Server, Terminal, X } from "lucide-react";
import { getInstanceDiagnostics, streamInstanceLogs, type InstanceDiagnosticsResponse, type InstanceResponse } from "@/api";
import { Button, Badge, LoadingState } from "@/shared/components";
import { formatApiError } from "@/shared/utils";
import { useToast } from "@/shared";

type TabKey = "summary" | "events" | "logs";

interface DiagnosticsModalProps {
  instance: InstanceResponse;
  onClose: () => void;
}

export const DiagnosticsModal: React.FC<DiagnosticsModalProps> = ({ instance, onClose }) => {
  const { success, error: toastError } = useToast();
  const [data, setData] = useState<InstanceDiagnosticsResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [activeTab, setActiveTab] = useState<TabKey>("summary");
  const [streamingKey, setStreamingKey] = useState<string | null>(null);
  const [streamingLines, setStreamingLines] = useState<string[]>([]);
  const streamCtrlRef = useRef<AbortController | null>(null);

  const loadDiagnostics = async () => {
    if (!instance.clusterId || !instance.id) return;
    setLoading(true);
    try {
      setData(await getInstanceDiagnostics({ clusterId: instance.clusterId, instanceId: instance.id }, { tailLines: 300 }));
    } catch (err) {
      toastError(formatApiError(err) || "Failed to load diagnostics");
    } finally {
      setLoading(false);
    }
  };

  const startStream = (pod: string, container: string) => {
    // Stop any existing stream first
    stopStream();
    const key = `${pod}/${container}`;
    setStreamingKey(key);
    setStreamingLines([]);
    const ctrl = streamInstanceLogs(
      instance.clusterId!,
      instance.id!,
      pod,
      container,
      200,
      (line) => setStreamingLines((prev) => [...prev, line]),
      () => { setStreamingKey(null); },
      (err) => { toastError(formatApiError(err) || "Stream error"); setStreamingKey(null); },
    );
    streamCtrlRef.current = ctrl;
  };

  const stopStream = () => {
    if (streamCtrlRef.current) {
      streamCtrlRef.current.abort();
      streamCtrlRef.current = null;
    }
    setStreamingKey(null);
    setStreamingLines([]);
  };

  useEffect(() => {
    void loadDiagnostics();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [instance.clusterId, instance.id]);

  // Cleanup stream on unmount
  useEffect(() => {
    return () => {
      if (streamCtrlRef.current) {
        streamCtrlRef.current.abort();
      }
    };
  }, []);

  const combinedLogs = useMemo(
    () =>
      (data?.logs ?? [])
        .map((entry) => `# ${entry.pod || "pod"} / ${entry.container || "container"}\n${entry.error || entry.log || ""}`)
        .join("\n\n"),
    [data?.logs]
  );

  const copyLogs = async () => {
    await navigator.clipboard.writeText(combinedLogs);
    success("Logs copied");
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-950/45 p-4 backdrop-blur-sm">
      <div className="flex max-h-[90vh] w-full max-w-6xl flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-2xl">
        <div className="flex items-start justify-between border-b border-slate-200 px-6 py-5">
          <div>
            <div className="flex items-center gap-2 text-sm font-semibold text-blue-700">
              <Activity className="h-4 w-4" />
              Runtime diagnostics
            </div>
            <h2 className="mt-1 text-xl font-semibold text-slate-950">{instance.name}</h2>
            <p className="mt-1 text-sm text-slate-500">
              {instance.namespace} · {data?.collectedAt ? new Date(data.collectedAt).toLocaleString() : "live Kubernetes data"}
            </p>
          </div>
          <div className="flex items-center gap-2">
            {streamingKey ? (
              <Button type="button" variant="danger" size="sm" onClick={stopStream}>
                Stop
              </Button>
            ) : (
              <Button type="button" variant="secondary" size="sm" icon={RotateCw} onClick={loadDiagnostics} loading={loading}>
                Refresh
              </Button>
            )}
            <button onClick={onClose} className="rounded-lg p-2 text-slate-500 hover:bg-slate-100 hover:text-slate-900">
              <X className="h-5 w-5" />
            </button>
          </div>
        </div>

        <div className="border-b border-slate-200 px-6 py-3">
          <div className="flex flex-wrap gap-2">
            <TabButton active={activeTab === "summary"} onClick={() => setActiveTab("summary")} icon={Box} label="Describe" />
            <TabButton active={activeTab === "events"} onClick={() => setActiveTab("events")} icon={AlertTriangle} label="Events" />
            <TabButton active={activeTab === "logs"} onClick={() => setActiveTab("logs")} icon={Terminal} label="Pod Logs" />
          </div>
        </div>

        <div className="flex-1 overflow-y-auto p-6">
          {loading ? (
            <LoadingState message="Loading Kubernetes diagnostics..." />
          ) : !data ? (
            <div className="rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800">
              Diagnostics data is not available.
            </div>
          ) : activeTab === "summary" ? (
            <SummaryTab data={data} />
          ) : activeTab === "events" ? (
            <EventsTab data={data} />
          ) : (
            <LogsTab
              data={data}
              combinedLogs={combinedLogs}
              onCopy={copyLogs}
              streamingKey={streamingKey}
              streamingLines={streamingLines}
              onStartStream={startStream}
              onStopStream={stopStream}
            />
          )}
        </div>
      </div>
    </div>
  );
};

const TabButton: React.FC<{
  active: boolean;
  icon: React.ComponentType<{ className?: string }>;
  label: string;
  onClick: () => void;
}> = ({ active, icon: Icon, label, onClick }) => (
  <button
    type="button"
    onClick={onClick}
    className={`inline-flex items-center gap-2 rounded-lg px-3 py-2 text-sm font-semibold transition ${
      active ? "bg-blue-600 text-white shadow-sm" : "bg-slate-100 text-slate-600 hover:bg-slate-200 hover:text-slate-950"
    }`}
  >
    <Icon className="h-4 w-4" />
    {label}
  </button>
);

const SummaryTab = ({ data }: { data: InstanceDiagnosticsResponse }) => (
  <div className="space-y-5">
    <div className="grid gap-4 md:grid-cols-3">
      <MetricCard icon={Box} label="Pods" value={data.pods?.length ?? 0} />
      <MetricCard icon={Server} label="Services" value={data.services?.length ?? 0} />
      <MetricCard icon={AlertTriangle} label="Events" value={data.events?.length ?? 0} />
    </div>
    <section className="space-y-3">
      <h3 className="text-sm font-semibold uppercase tracking-wide text-slate-500">Pods</h3>
      {(data.pods ?? []).length === 0 ? (
        <EmptyLine text="No pods matched this Helm release." />
      ) : (
        (data.pods ?? []).map((pod) => (
          <div key={pod.name} className="rounded-lg border border-slate-200 bg-slate-50 p-4">
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div>
                <h4 className="font-mono text-sm font-semibold text-slate-950">{pod.name}</h4>
                <p className="mt-1 text-xs text-slate-500">
                  {pod.nodeName || "unscheduled"} · podIP {pod.podIp || "-"} · restarts {pod.restartCount ?? 0}
                </p>
              </div>
              <Badge variant={pod.phase === "Running" ? "success" : "warning"} size="sm">
                {pod.phase || "Unknown"}
              </Badge>
            </div>
            <div className="mt-3 grid gap-2 md:grid-cols-2">
              {(pod.containers ?? []).map((container) => (
                <div key={container.name} className="rounded-md border border-slate-200 bg-white p-3">
                  <div className="flex items-center justify-between">
                    <span className="font-medium text-slate-900">{container.name}</span>
                    <Badge variant={container.ready ? "success" : "warning"} size="sm">
                      {container.state || "unknown"}
                    </Badge>
                  </div>
                  <p className="mt-1 truncate font-mono text-xs text-slate-500" title={container.image}>
                    {container.image}
                  </p>
                  {(container.reason || container.message) && (
                    <p className="mt-2 text-xs text-amber-700">{container.reason || container.message}</p>
                  )}
                </div>
              ))}
            </div>
          </div>
        ))
      )}
    </section>
    <section className="space-y-3">
      <h3 className="text-sm font-semibold uppercase tracking-wide text-slate-500">Services</h3>
      {(data.services ?? []).length === 0 ? <EmptyLine text="No services matched this Helm release." /> : null}
      {(data.services ?? []).map((svc) => (
        <div key={svc.name} className="rounded-lg border border-slate-200 bg-white p-4">
          <div className="flex items-center justify-between">
            <span className="font-mono text-sm font-semibold text-slate-950">{svc.name}</span>
            <Badge variant="secondary" size="sm">{svc.type}</Badge>
          </div>
          <p className="mt-1 text-xs text-slate-500">ClusterIP {svc.clusterIP || "-"}</p>
          <div className="mt-2 flex flex-wrap gap-2">
            {(svc.ports ?? []).map((port) => (
              <span key={`${port.name}-${port.port}`} className="rounded bg-slate-100 px-2 py-1 font-mono text-xs text-slate-700">
                {port.name || "port"} {port.port}:{port.targetPort}
              </span>
            ))}
          </div>
        </div>
      ))}
    </section>
  </div>
);

const EventsTab = ({ data }: { data: InstanceDiagnosticsResponse }) => (
  <div className="space-y-3">
    {(data.events ?? []).length === 0 ? <EmptyLine text="No Kubernetes events matched this release." /> : null}
    {(data.events ?? []).map((event, index) => (
      <div key={`${event.involvedName}-${event.reason}-${index}`} className="rounded-lg border border-slate-200 bg-white p-4">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div className="flex items-center gap-2">
            <Badge variant={event.type === "Warning" ? "warning" : "secondary"} size="sm">{event.type || "Normal"}</Badge>
            <span className="font-semibold text-slate-950">{event.reason}</span>
          </div>
          <span className="text-xs text-slate-500">{event.lastTimestamp ? new Date(event.lastTimestamp).toLocaleString() : ""}</span>
        </div>
        <p className="mt-2 text-sm text-slate-700">{event.message}</p>
        <p className="mt-2 text-xs text-slate-500">
          {event.involvedKind}/{event.involvedName} · count {event.count ?? 1}
        </p>
      </div>
    ))}
  </div>
);

const LogsTab = ({
  data,
  combinedLogs,
  onCopy,
  streamingKey,
  streamingLines,
  onStartStream,
  onStopStream,
}: {
  data: InstanceDiagnosticsResponse;
  combinedLogs: string;
  onCopy: () => void;
  streamingKey: string | null;
  streamingLines: string[];
  onStartStream: (pod: string, container: string) => void;
  onStopStream: () => void;
}) => {
  const preRef = useRef<HTMLPreElement>(null);

  useEffect(() => {
    if (streamingKey && preRef.current) {
      preRef.current.scrollTop = preRef.current.scrollHeight;
    }
  }, [streamingLines, streamingKey]);

  return (
    <div className="space-y-4">
      <div className="flex justify-end">
        <Button type="button" variant="secondary" size="sm" icon={Copy} onClick={onCopy} disabled={!combinedLogs}>
          Copy Logs
        </Button>
      </div>
      {(data.logs ?? []).length === 0 ? <EmptyLine text="No pod logs were returned." /> : null}
      {(data.logs ?? []).map((entry) => {
        const entryKey = `${entry.pod}/${entry.container}`;
        const isStreaming = streamingKey === entryKey;
        return (
          <div key={entryKey} className="overflow-hidden rounded-lg border border-slate-800 bg-slate-950">
            <div className="flex items-center gap-2 border-b border-slate-800 px-4 py-2 text-xs text-slate-300">
              <FileText className="h-3.5 w-3.5" />
              <span className="font-mono">{entryKey}</span>
              {isStreaming && (
                <span className="ml-auto inline-flex items-center gap-1.5">
                  <span className="h-2 w-2 rounded-full bg-emerald-400 animate-pulse" />
                  <span className="text-emerald-400">Live</span>
                </span>
              )}
              {isStreaming ? (
                <button
                  type="button"
                  onClick={onStopStream}
                  className="ml-2 rounded px-2 py-0.5 text-xs font-medium text-rose-400 hover:bg-rose-500/20 transition"
                >
                  Stop
                </button>
              ) : (
                <button
                  type="button"
                  onClick={() => onStartStream(entry.pod!, entry.container!)}
                  className="ml-auto rounded px-2 py-0.5 text-xs font-medium text-emerald-400 hover:bg-emerald-500/20 transition"
                >
                  Stream
                </button>
              )}
            </div>
            <pre
              ref={isStreaming ? preRef : undefined}
              className="max-h-96 overflow-auto p-4 text-xs leading-5 text-slate-100"
            >
              {isStreaming
                ? streamingLines.join("\n") || "Waiting for log data..."
                : entry.error || entry.log || ""}
            </pre>
          </div>
        );
      })}
    </div>
  );
};

const MetricCard = ({ icon: Icon, label, value }: { icon: React.ComponentType<{ className?: string }>; label: string; value: number }) => (
  <div className="rounded-lg border border-slate-200 bg-white p-4">
    <div className="flex items-center justify-between">
      <span className="text-sm font-medium text-slate-500">{label}</span>
      <Icon className="h-5 w-5 text-blue-600" />
    </div>
    <p className="mt-2 text-3xl font-semibold text-slate-950">{value}</p>
  </div>
);

const EmptyLine = ({ text }: { text: string }) => (
  <div className="rounded-lg border border-slate-200 bg-slate-50 p-4 text-sm text-slate-500">{text}</div>
);
