import { Action, ActionPanel, Clipboard, Icon, List, Cache, showHUD, popToRoot } from "@raycast/api";
import { useState } from "react";

const cache = new Cache();
const MODE_CACHE_KEY = "selected-mode";
const MODE_CACHE_TTL = 5 * 60 * 1000; // 5 minutes

const LOCAL_DOMAIN = "code.anton-atom.com";

type Mode = "local-fallback" | "prod-only" | "local-only";

interface ModeOption {
  id: Mode;
  title: string;
  description: string;
  icon: Icon;
}

const modes: ModeOption[] = [
  {
    id: "local-fallback",
    title: "Local + Fallback to Prod",
    description: "Try local first, fall back to prod after ~2s timeout",
    icon: Icon.ArrowLeftCircle,
  },
  {
    id: "prod-only",
    title: "Production Only",
    description: "Load only the production URL — safe to share",
    icon: Icon.Globe,
  },
  {
    id: "local-only",
    title: "Local Only",
    description: "Load only the local URL — for rapid dev testing",
    icon: Icon.Monitor,
  },
];

// ── URL conversion ──────────────────────────────────────────────

function localToProd(localUrl: string): string {
  const url = new URL(localUrl);
  const segments = url.pathname.split("/").filter(Boolean);
  if (segments.length < 1) throw new Error("URL has no path segments");
  const firstSegment = segments[0];
  const rest = segments.slice(1);
  const prodHost = `${firstSegment}.${url.host}`;
  const prodPath = rest.length > 0 ? "/" + rest.join("/") : "/";
  return `${url.protocol}//${prodHost}${prodPath}`;
}

// ── Snippet generators ──────────────────────────────────────────

function generateSingleSnippet(localUrl: string, prodUrl: string, mode: Mode): string {
  if (mode === "prod-only") {
    return `<script src="${prodUrl}"></script>`;
  }

  if (mode === "local-only") {
    return `<script src="${localUrl}"></script>`;
  }

  // local-fallback: try local <script>, on error silently swap to prod
  return `<script src="${localUrl}" onerror="(function(){var s=document.createElement('script');s.src='${prodUrl}';document.head.appendChild(s);})()"></script>`;
}

function generateBulkSnippet(scriptUrls: string[], mode: Mode): string {
  if (mode === "prod-only") {
    return scriptUrls.map((u) => `<script src="${localToProd(u)}"></script>`).join("\n");
  }

  if (mode === "local-only") {
    return scriptUrls.map((u) => `<script src="${u}"></script>`).join("\n");
  }

  // local-fallback: each script tries local, falls back to prod via onerror
  return scriptUrls
    .map((u) => {
      const prod = localToProd(u);
      return `<script src="${u}" onerror="(function(){var s=document.createElement('script');s.src='${prod}';document.head.appendChild(s);})()"></script>`;
    })
    .join("\n");
}

// ── Input parsing ───────────────────────────────────────────────

interface ParsedInput {
  type: "single-url" | "bulk-html";
  scriptUrls: string[];
  cssLines: string[];
}

function parseClipboard(text: string): ParsedInput | null {
  const trimmed = text.trim();

  // Case 1: bare URL
  if (trimmed.startsWith(`https://${LOCAL_DOMAIN}/`) && !trimmed.includes("<")) {
    return { type: "single-url", scriptUrls: [trimmed], cssLines: [] };
  }

  // Case 2: old IIFE snippet with { local: "...", prod: "..." } pairs
  const localPairRe = /local:\s*["']([^"']+)["']/g;
  let pairMatch;
  const pairUrls: string[] = [];
  while ((pairMatch = localPairRe.exec(trimmed)) !== null) {
    if (pairMatch[1].includes(LOCAL_DOMAIN)) {
      pairUrls.push(pairMatch[1]);
    }
  }
  if (pairUrls.length > 0) {
    return { type: "bulk-html", scriptUrls: pairUrls, cssLines: [] };
  }

  // Case 3: HTML block with <script> and/or <link> tags
  const lines = trimmed.split("\n").map((l) => l.trim()).filter(Boolean);
  const scriptUrls: string[] = [];
  const cssLines: string[] = [];

  const scriptSrcRe = /<script[^>]+src=["']([^"']+)["'][^>]*>/i;
  const linkHrefRe = /<link[^>]+href=["']([^"']+)["'][^>]*>/i;

  for (const line of lines) {
    const scriptMatch = line.match(scriptSrcRe);
    if (scriptMatch) {
      const src = scriptMatch[1];
      if (src.includes(LOCAL_DOMAIN)) {
        scriptUrls.push(src);
      }
      continue;
    }

    const linkMatch = line.match(linkHrefRe);
    if (linkMatch) {
      // Keep CSS lines as-is (skip conversion)
      cssLines.push(line);
      continue;
    }
  }

  if (scriptUrls.length === 0 && cssLines.length === 0) return null;

  return { type: "bulk-html", scriptUrls, cssLines };
}

// ── Processing ──────────────────────────────────────────────────

function getCachedMode(): Mode | null {
  const raw = cache.get(MODE_CACHE_KEY);
  if (!raw) return null;
  try {
    const data = JSON.parse(raw) as { mode: Mode; ts: number };
    if (Date.now() - data.ts < MODE_CACHE_TTL) return data.mode;
  } catch {
    // ignore
  }
  return null;
}

function setCachedMode(mode: Mode) {
  cache.set(MODE_CACHE_KEY, JSON.stringify({ mode, ts: Date.now() }));
}

function clearCachedMode() {
  cache.remove(MODE_CACHE_KEY);
}

async function processWithMode(mode: Mode) {
  const text = await Clipboard.readText();
  if (!text) {
    await showHUD("❌ Clipboard is empty");
    return;
  }

  const parsed = parseClipboard(text);
  if (!parsed || (parsed.scriptUrls.length === 0 && parsed.cssLines.length === 0)) {
    await showHUD("❌ No valid script URLs found in clipboard");
    return;
  }

  try {
    let result: string;

    if (parsed.type === "single-url" && parsed.scriptUrls.length === 1) {
      // Single bare URL
      const localUrl = parsed.scriptUrls[0];
      const prodUrl = localToProd(localUrl);
      result = generateSingleSnippet(localUrl, prodUrl, mode);
    } else {
      // Bulk HTML — CSS lines pass through, scripts get converted
      const parts: string[] = [];

      if (parsed.cssLines.length > 0) {
        parts.push(parsed.cssLines.join("\n"));
      }

      if (parsed.scriptUrls.length > 0) {
        parts.push(generateBulkSnippet(parsed.scriptUrls, mode));
      }

      result = parts.join("\n");
    }

    await Clipboard.copy(result);

    const count = parsed.scriptUrls.length;
    const cssCount = parsed.cssLines.length;
    const label = modes.find((m) => m.id === mode)?.title ?? mode;
    const detail = cssCount > 0 ? ` (${count} scripts + ${cssCount} CSS kept)` : ` (${count} script${count > 1 ? "s" : ""})`;
    await showHUD(`✅ ${label}${detail} copied`);
  } catch (e) {
    await showHUD(`❌ ${e instanceof Error ? e.message : "Failed to convert"}`);
  }
}

// ── Command ─────────────────────────────────────────────────────

export default function Command() {
  const cachedMode = getCachedMode();
  const [showPicker, setShowPicker] = useState(false);

  // If cache is active and user hasn't asked to change — run immediately
  if (cachedMode && !showPicker) {
    processWithMode(cachedMode).then(() => popToRoot());
    return null;
  }

  // Show mode picker
  return (
    <List searchBarPlaceholder="Pick a mode…">
      {modes.map((m) => {
        const isCurrent = cachedMode === m.id;
        return (
          <List.Item
            key={m.id}
            icon={m.icon}
            title={m.title}
            subtitle={m.description}
            accessories={isCurrent ? [{ tag: { value: "current" }, icon: Icon.Checkmark }] : []}
            actions={
              <ActionPanel>
                <Action
                  title="Select"
                  icon={Icon.Checkmark}
                  onAction={async () => {
                    setCachedMode(m.id);
                    await processWithMode(m.id);
                    await popToRoot();
                  }}
                />
              </ActionPanel>
            }
          />
        );
      })}
    </List>
  );
}
