import { useState, useRef, useEffect } from "react";
import { useRouterState, Link } from "@tanstack/react-router";
import { useMutation } from "@tanstack/react-query";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
import { useGenerationJobs, type ActiveJob } from "@/hooks/use-generation-jobs";
import { isTerminal } from "@/hooks/use-job-shared";
import { trpc, queryClient } from "@/utils/trpc";

interface LogEntry {
  step: string;
  message: string;
  status: "running" | "done" | "error";
  timestamp: string;
  details?: string;
}

const STEP_LABELS: Record<string, string> = {
  generate_passage: "Menulis Bacaan",
  validate_passage: "Memvalidasi Bacaan",
  generate_questions: "Membuat Soal",
  self_validate: "Self-Check Kualitas",
  save: "Menyimpan Hasil",
  cancel: "Dibatalkan",
  error: "Error",
};

function LogStatusIcon({ status }: { status: string }) {
  if (status === "done")
    return (
      <MaterialIcon
        name="check_circle"
        className="text-[var(--matcha-400)] text-xs shrink-0"
      />
    );
  if (status === "error")
    return (
      <MaterialIcon
        name="error"
        className="text-[var(--pomegranate-400)] text-xs shrink-0"
      />
    );
  return (
    <MaterialIcon
      name="sync"
      className="text-[var(--matcha-400)] text-xs shrink-0 animate-spin"
    />
  );
}

function TerminalLog({ logs, isRunning }: { logs: LogEntry[]; isRunning: boolean }) {
  const scrollRef = useRef<HTMLDivElement>(null);
  const [expandedIdx, setExpandedIdx] = useState<number | null>(null);

  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  }, [logs]);

  if (!logs?.length) {
    return (
      <div className="mt-2 rounded-lg bg-black/40 p-2 border border-white/5">
        <div className="flex items-center gap-2 text-white/40 text-[10px] font-mono">
          <MaterialIcon name="psychology" className="text-[10px] animate-pulse" />
          AI sedang mempersiapkan...
        </div>
      </div>
    );
  }

  return (
    <div
      ref={scrollRef}
      className="mt-2 max-h-32 overflow-y-auto rounded-lg bg-black/40 p-2 font-mono text-[10px] leading-relaxed border border-white/5"
    >
      {logs.map((log, i) => {
        const isExpanded = expandedIdx === i;
        const hasDetails = !!log.details && log.details.length > 0;
        const isLast = i === logs.length - 1;
        const isCurrentRunning = isLast && log.status === "running" && isRunning;

        return (
          <div key={i} className="flex flex-col">
            <div
              className={`flex items-start gap-1.5 py-0.5 ${hasDetails ? "cursor-pointer hover:bg-white/5 rounded px-1 -mx-1 transition-colors" : ""}`}
              onClick={() => hasDetails && setExpandedIdx(isExpanded ? null : i)}
            >
              <LogStatusIcon status={log.status} />
              <span className="text-white/30 shrink-0">
                {new Date(log.timestamp).toLocaleTimeString("id-ID", {
                  hour: "2-digit",
                  minute: "2-digit",
                })}
              </span>
              <span
                className={`font-semibold truncate ${
                  log.status === "error"
                    ? "text-[var(--pomegranate-400)]"
                    : log.status === "done"
                      ? "text-[var(--matcha-400)]"
                      : "text-white/80"
                }`}
              >
                {STEP_LABELS[log.step] ?? log.step}
              </span>
              {isCurrentRunning && (
                <span className="w-1 h-1 bg-[var(--matcha-400)] rounded-full animate-pulse shrink-0 mt-1" />
              )}
            </div>
            {isExpanded && hasDetails && (
              <div className="ml-5 mt-0.5 mb-1 p-2 rounded bg-black/60 border border-white/10 text-white/70 whitespace-pre-wrap text-[9px] leading-relaxed max-h-24 overflow-y-auto">
                {log.details}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

function SingleJobCard({
  job,
  onCancel,
  cancelPending,
}: {
  job: ActiveJob;
  onCancel: (jobId: string) => void;
  cancelPending: boolean;
}) {
  const [minimized, setMinimized] = useState(false);
  const progress = job.progress ?? 0;
  const message = job.progressMessage ?? "Sedang berjalan...";
  const logs = (job.logs ?? []) as LogEntry[];
  const isAgentic = job.mode === "agentic";

  if (minimized) {
    return (
      <button
        onClick={() => setMinimized(false)}
        className="flex items-center gap-2 py-1.5 px-3 bg-[var(--clay-black)]/90 rounded-lg text-white text-xs font-semibold border border-[var(--matcha-400)]/30 hover:border-[var(--matcha-400)]/60 transition-all w-full"
      >
        <MaterialIcon
          name="psychology"
          className="text-[var(--matcha-400)] animate-pulse text-xs"
        />
        <span className="truncate flex-1 text-left">{message}</span>
        <span className="tabular-nums text-[var(--matcha-400)]">{progress}%</span>
      </button>
    );
  }

  return (
    <div className="rounded-xl bg-[var(--clay-black)] border border-white/10 p-3 transition-all">
      <div className="flex items-center justify-between mb-2">
        <div className="flex items-center gap-2 min-w-0">
          <MaterialIcon
            name="psychology"
            className="text-[var(--matcha-400)] animate-pulse text-sm shrink-0"
          />
          <div className="min-w-0">
            <span className="text-xs font-semibold block truncate">{message}</span>
            {isAgentic && (
              <span className="text-[10px] text-[var(--matcha-400)]">Agentic</span>
            )}
          </div>
        </div>
        <div className="flex items-center gap-1 shrink-0">
          <button
            onClick={() => setMinimized(true)}
            className="w-6 h-6 flex items-center justify-center rounded-full hover:bg-white/10 text-white/50 hover:text-white transition-colors"
          >
            <MaterialIcon name="expand_less" className="text-xs" />
          </button>
          <button
            onClick={() => onCancel(job.id)}
            disabled={cancelPending}
            className="w-6 h-6 flex items-center justify-center rounded-full hover:bg-[var(--pomegranate-400)]/20 text-white/50 hover:text-[var(--pomegranate-400)] transition-colors disabled:opacity-30"
          >
            <MaterialIcon name="close" className="text-xs" />
          </button>
        </div>
      </div>

      <div className="mb-2">
        <div className="flex justify-between items-center mb-1">
          <span className="tabular-nums text-xs font-bold text-[var(--matcha-400)]">
            {progress}%
          </span>
        </div>
        <div className="w-full h-1.5 bg-white/20 rounded-full overflow-hidden">
          <div
            className="h-full bg-gradient-to-r from-[var(--matcha-600)] to-[var(--matcha-400)] transition-all duration-500 rounded-full"
            style={{ width: `${progress}%` }}
          />
        </div>
      </div>

      {isAgentic && <TerminalLog logs={logs} isRunning={!isTerminal(job.status)} />}
    </div>
  );
}

export function GlobalGenerationProgress() {
  const { activeJobs, isGenerating, removeJob, setError } = useGenerationJobs();
  const [collapsed, setCollapsed] = useState(false);

  const matches = useRouterState({ select: (s) => s.matches });
  const isGeneratePage = matches.some((m) => m.routeId === "/generate");
  const isTakePage = matches.some((m) => m.routeId === "/package/$id/take");

  const cancelMutation = useMutation({
    ...trpc.ai.cancelJob.mutationOptions(),
    onSuccess: async (_data, variables) => {
      removeJob(variables.jobId);
      setError(null);
      await queryClient.invalidateQueries({
        queryKey: trpc.ai.myJobs.queryKey(),
      });
    },
  });

  if (!isGenerating || isTakePage) return null;

  const handleCancel = (jobId: string) => {
    cancelMutation.mutate({ jobId });
  };

  // Collapsed floating pill showing count
  if (collapsed) {
    return (
      <button
        onClick={() => setCollapsed(false)}
        className="fixed bottom-8 right-6 z-50 h-11 pl-4 pr-5 bg-[var(--clay-black)] rounded-full flex items-center gap-2.5 text-white text-sm font-semibold shadow-2xl border border-[var(--matcha-400)]/30 hover:border-[var(--matcha-400)]/60 transition-all"
      >
        <MaterialIcon
          name="psychology"
          className="text-[var(--matcha-400)] animate-pulse text-sm"
        />
        <span>{activeJobs.length} active</span>
      </button>
    );
  }

  return (
    <div
      className={`fixed bottom-8 right-6 z-50 rounded-2xl shadow-2xl border p-4 text-white transition-all ${
        isGeneratePage
          ? "w-80 sm:w-[26rem] ring-2 ring-[var(--matcha-400)]/40 border-[var(--matcha-400)]/30 bg-[var(--clay-black)]"
          : "w-72 sm:w-80 border-white/10 bg-[var(--clay-black)]"
      }`}
    >
      <div className="flex items-center justify-between mb-3">
        <div className="flex items-center gap-2">
          <MaterialIcon
            name="psychology"
            className="text-[var(--matcha-400)] animate-pulse text-base"
          />
          <span className="text-sm font-semibold">
            AI Generation{activeJobs.length > 1 ? ` (${activeJobs.length})` : ""}
          </span>
        </div>
        <div className="flex items-center gap-1">
          <Link
            to="/generate"
            className="w-7 h-7 flex items-center justify-center rounded-full hover:bg-white/10 text-white/60 hover:text-white transition-colors"
            title="Buka halaman generate"
          >
            <MaterialIcon name="open_in_new" className="text-sm" />
          </Link>
          <button
            onClick={() => setCollapsed(true)}
            className="w-7 h-7 flex items-center justify-center rounded-full hover:bg-white/10 text-white/60 hover:text-white transition-colors"
            title="Minimize"
          >
            <MaterialIcon name="expand_more" className="text-sm" />
          </button>
        </div>
      </div>

      <div className="flex flex-col gap-2 max-h-[60vh] overflow-y-auto">
        {activeJobs.map((job) => (
          <SingleJobCard
            key={job.id}
            job={job}
            onCancel={handleCancel}
            cancelPending={cancelMutation.isPending}
          />
        ))}
      </div>
    </div>
  );
}
