import { useEffect, useMemo, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { useGalleryStore } from "../store";

type WorkerKey = "thumbnail" | "metadata" | "embedding";

const WORKER_FOR_STAGE: Record<string, WorkerKey> = {
  Thumbnails: "thumbnail",
  Metadata: "metadata",
  Embeddings: "embedding",
};

interface TaskStage {
  label: string;
  detail: string;
  progress: number | null; // 0–100, or null for indeterminate
  failed: boolean;
}

interface Task {
  id: number;
  name: string;
  stages: TaskStage[];
  hasFailedEmbeddings: boolean;
  pendingMediaWork: number;
  embeddingProcessed: number;
  embeddingTotal: number;
  currentFile: string | null;
  snapshot: string;
}

export function BackgroundTasks() {
  const folders = useGalleryStore((state) => state.folders);
  const indexingProgress = useGalleryStore((state) => state.indexingProgress);
  const mediaJobProgress = useGalleryStore((state) => state.mediaJobProgress);
  const retryFailedEmbeddings = useGalleryStore((state) => state.retryFailedEmbeddings);
  const [expanded, setExpanded] = useState(false);
  const [dismissed, setDismissed] = useState<Record<number, string>>({});
  const [paused, setPaused] = useState<Record<WorkerKey, boolean>>({
    thumbnail: false,
    metadata: false,
    embedding: false,
  });

  useEffect(() => {
    invoke<{ thumbnail_paused: boolean; metadata_paused: boolean; embedding_paused: boolean }>(
      "get_worker_states",
    ).then((states) => {
      setPaused({
        thumbnail: states.thumbnail_paused,
        metadata: states.metadata_paused,
        embedding: states.embedding_paused,
      });
    });
  }, []);

  const toggleWorker = (worker: WorkerKey) => {
    const next = !paused[worker];
    setPaused((prev) => ({ ...prev, [worker]: next }));
    void invoke("set_worker_paused", { worker, paused: next });
  };

  const dismissTask = (id: number, snapshot: string) => {
    setDismissed((prev) => ({ ...prev, [id]: snapshot }));
    setExpanded(false);
  };

  const tasks = useMemo<Task[]>(() => {
    return folders
      .map((folder): Task | null => {
        const index = indexingProgress[folder.id];
        const jobs = mediaJobProgress[folder.id];

        const thumbnailPending = jobs?.thumbnail_pending ?? 0;
        const metadataPending = jobs?.metadata_pending ?? 0;
        const embeddingPending = jobs?.embedding_pending ?? 0;
        const embeddingReady = jobs?.embedding_ready ?? 0;
        const embeddingFailed = jobs?.embedding_failed ?? 0;

        const pendingMediaWork = thumbnailPending + metadataPending + embeddingPending;
        const embeddingProcessed = embeddingReady + embeddingFailed;
        const embeddingTotal = embeddingProcessed + embeddingPending;
        const hasFailedEmbeddings = embeddingFailed > 0;

        if (!index && pendingMediaWork === 0 && !hasFailedEmbeddings) return null;

        const stages: TaskStage[] = [];

        if (index && !index.done) {
          const pct = index.total > 0 ? (index.indexed / index.total) * 100 : 0;
          stages.push({
            label: "Scanning",
            detail: `${index.indexed.toLocaleString()} / ${index.total.toLocaleString()}`,
            progress: pct,
            failed: false,
          });
        }

        if (thumbnailPending > 0) {
          stages.push({
            label: "Thumbnails",
            detail: thumbnailPending.toLocaleString(),
            progress: null,
            failed: false,
          });
        }

        if (metadataPending > 0) {
          stages.push({
            label: "Metadata",
            detail: metadataPending.toLocaleString(),
            progress: null,
            failed: false,
          });
        }

        if (embeddingPending > 0) {
          const pct = embeddingTotal > 0 ? (embeddingProcessed / embeddingTotal) * 100 : 0;
          stages.push({
            label: "Embeddings",
            detail: `${embeddingProcessed.toLocaleString()} / ${embeddingTotal.toLocaleString()}`,
            progress: pct,
            failed: false,
          });
        }

        if (hasFailedEmbeddings && pendingMediaWork === 0) {
          stages.push({
            label: "Failed",
            detail: `${embeddingFailed.toLocaleString()} embeddings`,
            progress: null,
            failed: true,
          });
        }

        const snapshot = `${pendingMediaWork}:${embeddingFailed}`;

        return {
          id: folder.id,
          name: folder.name,
          stages,
          hasFailedEmbeddings,
          pendingMediaWork,
          embeddingProcessed,
          embeddingTotal,
          currentFile: index && !index.done ? (index.current_file || null) : null,
          snapshot,
        };
      })
      .filter((t): t is Task => t !== null)
      .filter((t) => dismissed[t.id] !== t.snapshot);
  }, [folders, indexingProgress, mediaJobProgress, dismissed]);

  if (tasks.length === 0) return null;

  const primary = tasks[0];
  const extraCount = tasks.length - 1;
  const hasFailed = tasks.some((t) => t.hasFailedEmbeddings && t.pendingMediaWork === 0);

  // Best progress bar value: use embedding progress if available (most informative),
  // otherwise fall back to scanning progress, otherwise indeterminate.
  const embeddingStage = primary.stages.find((s) => s.label === "Embeddings");
  const scanningStage = primary.stages.find((s) => s.label === "Scanning");
  const barProgress = embeddingStage?.progress ?? scanningStage?.progress ?? null;

  return (
    <div className="shrink-0 border-b border-white/[0.06]">
      {/* Slim bar */}
      <div
        className={`group flex items-center gap-3 px-5 h-11 cursor-pointer select-none transition-colors ${
          expanded ? "bg-white/[0.03]" : "hover:bg-white/[0.02]"
        }`}
        onClick={() => setExpanded((v) => !v)}
      >
        {/* Pulse dot */}
        <div className="relative shrink-0">
          <div className={`h-1.5 w-1.5 rounded-full ${hasFailed ? "bg-amber-400" : "bg-blue-400"}`} />
          <div className={`absolute inset-0 h-1.5 w-1.5 rounded-full animate-ping opacity-60 ${hasFailed ? "bg-amber-400" : "bg-blue-400"}`} />
        </div>

        {/* Folder name */}
        <span className="text-[13px] font-medium text-white/60 shrink-0">{primary.name}</span>

        {/* Stage tags — all active stages visible simultaneously */}
        <div className="flex items-center gap-1.5 flex-1 min-w-0 overflow-hidden">
          {primary.stages.map((stage) => {
            const workerKey = WORKER_FOR_STAGE[stage.label];
            const isPaused = workerKey ? paused[workerKey] : false;
            return (
              <span
                key={stage.label}
                className={`flex items-center gap-1 rounded-md px-2 py-0.5 text-[11px] shrink-0 ${
                  stage.failed
                    ? "bg-amber-500/10 text-amber-400"
                    : isPaused
                      ? "bg-white/4 text-gray-600"
                      : "bg-white/5 text-gray-400"
                }`}
              >
                <span>{stage.label}</span>
                <span className={`tabular-nums ${stage.failed ? "text-amber-500" : isPaused ? "text-gray-700" : "text-gray-600"}`}>
                  {stage.detail}
                </span>
                {workerKey && (
                  <button
                    className="ml-0.5 opacity-0 group-hover:opacity-100 hover:text-white transition-opacity"
                    title={isPaused ? `Resume ${stage.label}` : `Pause ${stage.label}`}
                    onClick={(e) => { e.stopPropagation(); toggleWorker(workerKey); }}
                  >
                    {isPaused ? (
                      <svg className="h-2.5 w-2.5" fill="currentColor" viewBox="0 0 24 24">
                        <path d="M8 5v14l11-7z" />
                      </svg>
                    ) : (
                      <svg className="h-2.5 w-2.5" fill="currentColor" viewBox="0 0 24 24">
                        <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
                      </svg>
                    )}
                  </button>
                )}
              </span>
            );
          })}
        </div>

        {/* Progress bar — embedding or scanning progress, pulsing if indeterminate */}
        <div className="w-24 h-px bg-white/8 rounded-full overflow-hidden shrink-0">
          <div
            className={`h-full rounded-full transition-all duration-500 ${
              hasFailed
                ? "bg-amber-400/60"
                : barProgress === null
                  ? "bg-blue-500/40 animate-pulse w-full"
                  : "bg-blue-500"
            }`}
            style={barProgress !== null ? { width: `${barProgress}%` } : undefined}
          />
        </div>

        {/* Extra folders badge */}
        {extraCount > 0 && (
          <span className="rounded-full bg-white/8 px-2 py-0.5 text-[10px] text-gray-500 shrink-0">
            +{extraCount}
          </span>
        )}

        {/* Retry (failed embeddings only) */}
        {primary.hasFailedEmbeddings && primary.pendingMediaWork === 0 && (
          <button
            className="rounded-lg border border-amber-500/20 bg-amber-500/10 px-2.5 py-1 text-[11px] text-amber-300 hover:bg-amber-500/20 transition-colors shrink-0"
            onClick={(e) => { e.stopPropagation(); void retryFailedEmbeddings(primary.id); }}
          >
            Retry
          </button>
        )}

        {/* Expand chevron (only when multiple folders) */}
        {tasks.length > 1 && (
          <svg
            className={`h-3.5 w-3.5 text-gray-600 transition-transform duration-200 shrink-0 ${expanded ? "rotate-180" : ""}`}
            fill="none" viewBox="0 0 24 24" stroke="currentColor"
          >
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
          </svg>
        )}

        {/* Dismiss */}
        <button
          className="p-1 rounded-md text-gray-600 hover:text-gray-300 hover:bg-white/8 transition-colors shrink-0"
          title="Dismiss"
          onClick={(e) => { e.stopPropagation(); dismissTask(primary.id, primary.snapshot); }}
        >
          <svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>

      {/* Expanded panel — one row per folder */}
      {expanded && (
        <div className="border-t border-white/[0.06] bg-white/[0.02] px-5 py-3 space-y-3">
          {tasks.map((task) => {
            const taskEmbeddingStage = task.stages.find((s) => s.label === "Embeddings");
            const taskScanningStage = task.stages.find((s) => s.label === "Scanning");
            const taskBarProgress = taskEmbeddingStage?.progress ?? taskScanningStage?.progress ?? null;
            const taskHasFailed = task.hasFailedEmbeddings && task.pendingMediaWork === 0;

            return (
              <div key={task.id}>
                <div className="flex items-center gap-3">
                  <span className="text-[12px] text-white/50 w-28 truncate shrink-0">{task.name}</span>

                  <div className="flex items-center gap-1.5 flex-1 min-w-0 overflow-hidden">
                    {task.stages.map((stage) => {
                      const workerKey = WORKER_FOR_STAGE[stage.label];
                      const isPaused = workerKey ? paused[workerKey] : false;
                      return (
                        <span
                          key={stage.label}
                          className={`flex items-center gap-1 rounded-md px-2 py-0.5 text-[11px] shrink-0 ${
                            stage.failed
                              ? "bg-amber-500/10 text-amber-400"
                              : isPaused
                                ? "bg-white/4 text-gray-600"
                                : "bg-white/5 text-gray-500"
                          }`}
                        >
                          {isPaused && (
                            <svg className="h-2 w-2 text-gray-600" fill="currentColor" viewBox="0 0 24 24">
                              <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
                            </svg>
                          )}
                          <span>{stage.label}</span>
                          <span className={`tabular-nums ${stage.failed ? "text-amber-500" : "text-gray-600"}`}>
                            {stage.detail}
                          </span>
                          {workerKey && (
                            <button
                              className="ml-0.5 text-gray-600 hover:text-white transition-colors"
                              title={isPaused ? `Resume ${stage.label}` : `Pause ${stage.label}`}
                              onClick={() => toggleWorker(workerKey)}
                            >
                              {isPaused ? (
                                <svg className="h-2.5 w-2.5" fill="currentColor" viewBox="0 0 24 24">
                                  <path d="M8 5v14l11-7z" />
                                </svg>
                              ) : (
                                <svg className="h-2.5 w-2.5" fill="currentColor" viewBox="0 0 24 24">
                                  <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
                                </svg>
                              )}
                            </button>
                          )}
                        </span>
                      );
                    })}
                  </div>

                  <div className="w-20 h-px bg-white/8 rounded-full overflow-hidden shrink-0">
                    <div
                      className={`h-full rounded-full transition-all duration-500 ${
                        taskHasFailed
                          ? "bg-amber-400/60"
                          : taskBarProgress === null
                            ? "bg-blue-500/40 animate-pulse w-full"
                            : "bg-blue-500"
                      }`}
                      style={taskBarProgress !== null ? { width: `${taskBarProgress}%` } : undefined}
                    />
                  </div>

                  {taskHasFailed && (
                    <button
                      className="rounded-lg border border-amber-500/20 bg-amber-500/10 px-2 py-0.5 text-[11px] text-amber-300 hover:bg-amber-500/20 transition-colors shrink-0"
                      onClick={() => void retryFailedEmbeddings(task.id)}
                    >
                      Retry
                    </button>
                  )}

                  <button
                    className="p-1 rounded-md text-gray-600 hover:text-gray-300 hover:bg-white/8 transition-colors shrink-0"
                    title="Dismiss"
                    onClick={() => dismissTask(task.id, task.snapshot)}
                  >
                    <svg className="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
                    </svg>
                  </button>
                </div>

                {task.currentFile && (
                  <p className="text-[10px] text-gray-600 truncate mt-1 pl-[calc(7rem+0.75rem)]">
                    {task.currentFile}
                  </p>
                )}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}
