"use client";

import { useEffect, useState } from "react";

type Phase = "scraping" | "enriching" | "emails" | "topping" | "done";

interface JobStatus {
  status: "running" | "complete" | "failed";
  totalLeads: number;
  emailsFound: number;
  error?: string | null;
  results?: LeadResult[];
}

export interface LeadResult {
  id: string;
  companyName: string | null;
  domain: string | null;
  contactName: string | null;
  contactTitle: string | null;
  email: string | null;
  linkedinUrl: string | null;
  address: string | null;
  phone: string | null;
  createdAt: string;
  isNew: boolean;
}

interface LoadingCardProps {
  jobId: string;
  targetCount: number;
  query: string;
  region: string;
  onDone: (leads: LeadResult[], warning?: string) => void;
  onError: (message: string) => void;
}

const STEPS = [
  { id: "scraping" as Phase, label: "Unternehmen gefunden" },
  { id: "enriching" as Phase, label: "Kontakte ermitteln" },
  { id: "emails" as Phase, label: "E-Mails suchen" },
  { id: "done" as Phase, label: "Fertig" },
];

function getPhase(s: JobStatus): Phase {
  if (s.status === "complete") return "done";
  if (s.emailsFound > 0) return "emails";
  if (s.totalLeads > 0) return "enriching";
  return "scraping";
}

function stepState(step: Phase, currentPhase: Phase): "done" | "active" | "pending" {
  const order: Phase[] = ["scraping", "enriching", "emails", "done"];
  const stepIdx = order.indexOf(step);
  const currentIdx = order.indexOf(currentPhase);
  if (stepIdx < currentIdx) return "done";
  if (stepIdx === currentIdx) return "active";
  return "pending";
}

const PHASE_MIN: Record<Phase, number> = {
  scraping: 3,
  enriching: 35,
  emails: 60,
  topping: 88,
  done: 100,
};

export function LoadingCard({ jobId, targetCount, query, region, onDone, onError }: LoadingCardProps) {
  const [phase, setPhase] = useState<Phase>("scraping");
  const [totalLeads, setTotalLeads] = useState(0);
  const [emailsFound, setEmailsFound] = useState(0);
  const [progressWidth, setProgressWidth] = useState(3);
  const [isTopping, setIsTopping] = useState(false);
  const [optimizedQuery, setOptimizedQuery] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    let crawlInterval: ReturnType<typeof setInterval> | null = null;
    let mapsPollTimeout: ReturnType<typeof setTimeout> | null = null;
    let serpPollTimeout: ReturnType<typeof setTimeout> | null = null;

    // Parallel tracking
    let supplementStarted = false;
    let mapsDone = false;
    let serpDone = false;
    let serpNeeded = false;
    let mapsLeads: LeadResult[] = [];
    let serpLeads: LeadResult[] = [];
    let serpJobId: string | null = null;
    let lastTotalLeads = 0; // detect when Maps scraping has stabilized

    function advanceBar(to: number) {
      setProgressWidth(prev => Math.max(prev, to));
    }

    crawlInterval = setInterval(() => {
      if (cancelled) return;
      setProgressWidth(prev => prev >= 88 ? prev : prev + 0.4);
    }, 200);

    // Called when both Maps and SERP (if needed) are done
    function tryFinalize() {
      if (!mapsDone || (serpNeeded && !serpDone)) return;
      if (crawlInterval) clearInterval(crawlInterval);

      let finalLeads: LeadResult[];
      if (serpNeeded && serpLeads.length > 0) {
        const seenDomains = new Set(mapsLeads.map(l => l.domain).filter(Boolean));
        const newSerpLeads = serpLeads.filter(l => !l.domain || !seenDomains.has(l.domain));
        finalLeads = [...mapsLeads, ...newSerpLeads];
      } else {
        finalLeads = mapsLeads;
      }

      setTotalLeads(finalLeads.length);
      setProgressWidth(100);
      setPhase("done");
      setTimeout(() => { if (!cancelled) onDone(finalLeads); }, 800);
    }

    // Start SERP supplement in parallel — doesn't block Maps polling
    async function startSerpSupplement(foundCount: number) {
      supplementStarted = true;
      serpNeeded = true;
      setIsTopping(true);

      try {
        const res = await fetch("/api/search/supplement", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ query, region, targetCount, foundCount }),
        });
        if (!res.ok) throw new Error("supplement start failed");
        const data = await res.json() as { jobId: string; optimizedQuery: string; usedAI: boolean };
        serpJobId = data.jobId;
        if (data.optimizedQuery) setOptimizedQuery(data.optimizedQuery);
        serpPollTimeout = setTimeout(pollSerp, 2500);
      } catch {
        // Supplement failed — mark done with no results so tryFinalize can proceed
        serpDone = true;
        tryFinalize();
      }
    }

    // Independent SERP poll loop
    async function pollSerp() {
      if (cancelled || !serpJobId) return;
      try {
        const res = await fetch(`/api/jobs/${serpJobId}/status`);
        if (!res.ok) throw new Error("fetch failed");
        const data = await res.json() as JobStatus;
        if (!cancelled) {
          if (data.status === "complete" || data.status === "failed") {
            serpLeads = (data.results ?? []) as LeadResult[];
            serpDone = true;
            tryFinalize();
          } else {
            serpPollTimeout = setTimeout(pollSerp, 2500);
          }
        }
      } catch {
        if (!cancelled) serpPollTimeout = setTimeout(pollSerp, 3000);
      }
    }

    // Maps poll loop
    async function pollMaps() {
      if (cancelled) return;
      try {
        const res = await fetch(`/api/jobs/${jobId}/status`);
        if (!res.ok) throw new Error("fetch failed");
        const data = await res.json() as JobStatus;

        if (!cancelled) {
          setTotalLeads(data.totalLeads);
          setEmailsFound(data.emailsFound);
          const p = getPhase(data);
          setPhase(p);
          advanceBar(PHASE_MIN[p]);

          // Fire supplement as soon as Maps scraping stabilizes with fewer results than needed.
          // "Stabilized" = totalLeads unchanged since last poll (scraping done, enrichment started).
          if (
            !supplementStarted &&
            data.status === "running" &&
            data.totalLeads > 0 &&
            data.totalLeads < targetCount &&
            data.totalLeads === lastTotalLeads
          ) {
            startSerpSupplement(data.totalLeads).catch(console.error);
          }
          lastTotalLeads = data.totalLeads;

          if (data.status === "complete" || data.status === "failed") {
            const leads = (data.results ?? []) as LeadResult[];

            if (data.status === "failed" && leads.length === 0) {
              if (crawlInterval) clearInterval(crawlInterval);
              onError(data.error ?? "Unbekannter Fehler");
              return;
            }

            // Flash "E-Mails suchen" step before completing (poll often misses it)
            setPhase("emails");
            advanceBar(PHASE_MIN["emails"]);
            await new Promise(r => setTimeout(r, 500));
            if (cancelled) return;

            mapsLeads = leads;
            mapsDone = true;

            // If supplement wasn't triggered, no SERP needed
            if (!supplementStarted) serpDone = true;

            // Trigger supplement now if Maps finished with fewer results and we haven't yet
            if (!supplementStarted && data.totalLeads < targetCount) {
              startSerpSupplement(data.totalLeads).catch(console.error);
            } else {
              tryFinalize();
            }
          } else {
            mapsPollTimeout = setTimeout(pollMaps, 2500);
          }
        }
      } catch {
        if (!cancelled) mapsPollTimeout = setTimeout(pollMaps, 3000);
      }
    }

    pollMaps();

    return () => {
      cancelled = true;
      if (crawlInterval) clearInterval(crawlInterval);
      if (mapsPollTimeout) clearTimeout(mapsPollTimeout);
      if (serpPollTimeout) clearTimeout(serpPollTimeout);
    };
  }, [jobId]); // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <div
      style={{
        background: "#111118",
        border: "1px solid #1e1e2e",
        borderRadius: 12,
        padding: 24,
        marginTop: 16,
      }}
    >
      {/* Header */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14 }}>
        <span style={{ fontSize: 13, fontWeight: 500, color: "#ffffff" }}>
          {isTopping ? "Ergebnisse werden ergänzt" : "Ergebnisse werden gesucht"}
        </span>
        <span style={{ fontSize: 12, color: "#9ca3af" }}>
          {totalLeads > 0 || emailsFound > 0
            ? `${emailsFound} E-Mails · ${totalLeads} Unternehmen`
            : "Wird gestartet…"}
        </span>
      </div>

      {/* Progress bar — only ever moves forward */}
      <div
        style={{
          height: 5,
          borderRadius: 3,
          background: "#1e1e2e",
          overflow: "hidden",
          marginBottom: 16,
        }}
      >
        <div
          style={{
            height: "100%",
            width: `${progressWidth}%`,
            background: "linear-gradient(90deg, #3b82f6, #8b5cf6)",
            borderRadius: 3,
            transition: phase === "done" ? "width 0.5s ease" : "width 0.12s linear",
          }}
        />
      </div>

      {/* Steps */}
      <div style={{ display: "flex", gap: 20, marginBottom: 16, flexWrap: "wrap" }}>
        {STEPS.map((step) => {
          const state = isTopping ? "done" : stepState(step.id, phase);
          return (
            <div key={step.id} style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <div
                style={{
                  width: 6,
                  height: 6,
                  borderRadius: 3,
                  background: state === "done" ? "#22c55e" : state === "active" ? "#3b82f6" : "#2e2e3e",
                  animation: state === "active" ? "pulse 1.5s infinite" : "none",
                }}
              />
              <span
                style={{
                  fontSize: 12,
                  color: state === "done" ? "#22c55e" : state === "active" ? "#ffffff" : "#6b7280",
                }}
              >
                {step.label}
              </span>
            </div>
          );
        })}
        {isTopping && (
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            <div style={{ width: 6, height: 6, borderRadius: 3, background: "#3b82f6", animation: "pulse 1.5s infinite" }} />
            <span style={{ fontSize: 12, color: "#ffffff" }}>Ergebnisse auffüllen</span>
          </div>
        )}
      </div>

      {/* Optimized query hint */}
      {isTopping && optimizedQuery && (
        <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 14, fontSize: 11, color: "#6b7280" }}>
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" strokeWidth="2.5">
            <path d="M9.663 17h4.673M12 3v1m6.364 1.636-.707.707M21 12h-1M4 12H3m3.343-5.657-.707-.707m2.828 9.9a5 5 0 1 1 7.072 0l-.548.547A3.374 3.374 0 0 0 14 18.469V19a2 2 0 1 1-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/>
          </svg>
          KI-optimierte Suche:&nbsp;
          <span style={{ color: "#9ca3af", fontStyle: "italic" }}>„{optimizedQuery}"</span>
        </div>
      )}

      {/* Warning banner */}
      <div
        style={{
          borderLeft: "3px solid #f59e0b",
          background: "rgba(245,158,11,0.08)",
          padding: "10px 14px",
          borderRadius: 8,
          fontSize: 12,
          color: "#9ca3af",
        }}
      >
        ⚠️ Bitte diesen Tab nicht schließen, während die Suche läuft.
      </div>

      <style>{`
        @keyframes pulse {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.3; }
        }
      `}</style>
    </div>
  );
}
