import { Alpine } from "./alpine";
import { showToast } from "./toast";

async function scanAllLibraries(): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  try {
    const libsResp = await fetch("/api/libraries", {
      headers: { Authorization: `Bearer ${token}` },
    });

    if (!libsResp.ok) {
      throw new Error("Failed to get libraries");
    }

    const libsData = await libsResp.json();

    if (!libsData.data || libsData.data.length === 0) {
      showToast("No libraries found. Please create a library first.", "error");
      return;
    }

    const libraries = libsData.data;

    const jobs: string[] = [];
    const libraryNames: Record<string, string> = {};

    for (const lib of libraries) {
      const scanResp = await fetch(`/api/libraries/${lib.id}/scan`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ force: true }),
      });

      if (scanResp.ok) {
        const result = await scanResp.json();
        jobs.push(result.job_id);
        libraryNames[result.job_id] = lib.name;
      } else {
        console.error(`Failed to scan library: ${lib.name}`);
      }
    }

    if (jobs.length === 0) {
      showToast("Failed to start scan for any library", "error");
      return;
    }

    showScanProgress(jobs, libraryNames);
  } catch (error) {
    console.error("Scan error:", error);
    showToast("Failed to start scan: " + (error as Error).message, "error");
  }
}

function showScanProgress(
  jobIds: string[],
  libraryNames: Record<string, string>,
): void {
  const container = document.getElementById(
    "scan-progress-container",
  ) as HTMLElement;
  const list = document.getElementById("library-progress-list") as HTMLElement;

  if (!container || !list) return;

  container.classList.remove("hidden");
  container.classList.remove("opacity-0", "-translate-y-2.5");

  list.innerHTML = jobIds
    .map(
      (jobId) => `
        <div id="progress-${jobId}" class="p-3 rounded border"
             style="background-color: var(--bg-primary); border-color: var(--border);">
            <div class="flex justify-between items-center mb-2">
                <span class="font-medium" style="color: var(--text-primary)">
                    ${libraryNames[jobId]}
                </span>
                <span id="status-${jobId}" class="text-sm" style="color: var(--text-secondary)">
                    Pending...
                </span>
            </div>
            <div class="w-full bg-gray-700 rounded-full h-2">
                <div id="bar-${jobId}"
                     class="h-2 rounded-full transition-all duration-500"
                     style="width: 0%; background-color: var(--accent);">
                </div>
            </div>
        </div>
    `,
    )
    .join("");

  pollScanProgress(jobIds, libraryNames);
}

let scanPollInterval: ReturnType<typeof setInterval> | undefined = undefined;

function pollScanProgress(
  jobIds: string[],
  _libraryNames: Record<string, string>,
): void {
  const token = localStorage.getItem("token");
  const startTime = Date.now();
  scanPollInterval = setInterval(async () => {
    let allComplete = true;
    let totalProgress = 0;
    let totalFiles = 0;
    let totalNewItems = 0;
    let totalErrors = 0;

    for (const jobId of jobIds) {
      try {
        const resp = await fetch(`/api/scanner/status/${jobId}`, {
          headers: { Authorization: `Bearer ${token}` },
        });

        if (resp.ok) {
          const status = await resp.json();

          updateLibraryProgress(jobId, status);

          totalProgress += status.progress || 0;
          totalFiles += status.files_scanned || 0;
          totalNewItems += status.new_items || 0;
          totalErrors += status.errors || 0;

          if (status.status !== "completed" && status.status !== "failed") {
            allComplete = false;
          }
        }
      } catch (error) {
        console.error(`Failed to poll job ${jobId}:`, error);
      }
    }

    const overallProgress = Math.round(totalProgress / jobIds.length);
    const progressBar = document.getElementById(
      "scan-progress-bar",
    ) as HTMLElement;
    const progressText = document.getElementById(
      "scan-progress-text",
    ) as HTMLElement;
    const statusText = document.getElementById("scan-status") as HTMLElement;

    if (progressBar) progressBar.style.width = overallProgress + "%";
    if (progressText) progressText.textContent = overallProgress + "%";

    const elapsed = Math.round((Date.now() - startTime) / 1000);
    if (!allComplete && statusText) {
      statusText.textContent = `Scanning... ${elapsed}s elapsed • ${totalFiles} files processed`;
    }

    if (allComplete) {
      clearInterval(scanPollInterval!);
      showScanResults(
        jobIds.length,
        totalFiles,
        totalNewItems,
        totalErrors,
        elapsed,
      );
    }
  }, 2000);
}

function updateLibraryProgress(jobId: string, status: any): void {
  const bar = document.getElementById(`bar-${jobId}`) as HTMLElement;
  const statusText = document.getElementById(`status-${jobId}`) as HTMLElement;

  if (bar) {
    bar.style.width = (status.progress || 0) + "%";
  }

  if (statusText) {
    const statusMessages: Record<string, string> = {
      pending: "Pending...",
      running: `Scanning... ${status.progress || 0}%`,
      completed: `✓ Complete (${status.new_items || 0} items)`,
      failed: `✗ Failed`,
    };
    statusText.textContent = statusMessages[status.status] || status.status;
  }
}

function showScanResults(
  libCount: number,
  files: number,
  items: number,
  errors: number,
  elapsed: number,
): void {
  const resultsDiv = document.getElementById("scan-results") as HTMLElement;
  const contentDiv = document.getElementById(
    "scan-results-content",
  ) as HTMLElement;

  if (!resultsDiv || !contentDiv) return;

  contentDiv.innerHTML = `
        <p>• ${libCount} librar${libCount === 1 ? "y" : "ies"} scanned</p>
        <p>• ${files} files processed</p>
        <p>• ${items} new items added</p>
        ${errors > 0 ? `<p style="color: var(--accent);">• ${errors} errors</p>` : ""}
        <p style="color: var(--text-secondary)">Completed in ${elapsed} seconds</p>
    `;

  resultsDiv.classList.remove("hidden");

  const statusText = document.getElementById("scan-status") as HTMLElement;
  if (statusText) statusText.textContent = "Scan complete!";
}

function hideScanProgress(): void {
  const container = document.getElementById(
    "scan-progress-container",
  ) as HTMLElement;
  if (container) container.classList.add("hidden");
}

async function loadWatchStatus(): Promise<void> {
  const token = localStorage.getItem("token");
  if (!token) return;

  try {
    const response = await fetch("/api/scanner/watch/status", {
      headers: { Authorization: `Bearer ${token}` },
    });
    if (response.ok) {
      const data = await response.json();
      const countEl = document.getElementById("watch-count");
      if (countEl) {
        countEl.textContent = data.total_watching?.toString() || "0";
      }
    }
  } catch (error) {
    console.error("Failed to load watch status:", error);
  }
}

function stopScanStatusPolling(): void {
  if (scanPollInterval !== undefined) {
    clearInterval(scanPollInterval);
    scanPollInterval = undefined;
  }
}

export {
  hideScanProgress,
  loadWatchStatus,
  scanAllLibraries,
  stopScanStatusPolling,
};

Alpine.data("admin", () => ({
  hideScanProgress,
  loadWatchStatus,
  scanAllLibraries,
  stopScanStatusPolling,
}));
