
"use client";

import React, { useState, useEffect, useCallback, useMemo } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Snippet } from "@/lib/directus";
import { X, Copy, Check, ChevronLeft, ChevronRight, Search } from "lucide-react";

// Color-coded language badges using the liquid design palette
const LANG_STYLES: Record<string, { bg: string; text: string; label: string }> = {
  typescript:  { bg: "bg-liquid-lavender/40", text: "text-purple-700 dark:text-purple-300", label: "TS" },
  ts:          { bg: "bg-liquid-lavender/40", text: "text-purple-700 dark:text-purple-300", label: "TS" },
  javascript:  { bg: "bg-liquid-amber/40",    text: "text-amber-700 dark:text-amber-300",   label: "JS" },
  js:          { bg: "bg-liquid-amber/40",    text: "text-amber-700 dark:text-amber-300",   label: "JS" },
  python:      { bg: "bg-liquid-sky/40",      text: "text-sky-700 dark:text-sky-300",       label: "PY" },
  bash:        { bg: "bg-liquid-mint/40",     text: "text-emerald-700 dark:text-emerald-300", label: "SH" },
  shell:       { bg: "bg-liquid-mint/40",     text: "text-emerald-700 dark:text-emerald-300", label: "SH" },
  sh:          { bg: "bg-liquid-mint/40",     text: "text-emerald-700 dark:text-emerald-300", label: "SH" },
  dockerfile:  { bg: "bg-liquid-blue/40",     text: "text-blue-700 dark:text-blue-300",     label: "🐳" },
  docker:      { bg: "bg-liquid-blue/40",     text: "text-blue-700 dark:text-blue-300",     label: "🐳" },
  css:         { bg: "bg-liquid-pink/40",     text: "text-pink-700 dark:text-pink-300",     label: "CSS" },
  scss:        { bg: "bg-liquid-pink/40",     text: "text-pink-700 dark:text-pink-300",     label: "SCSS" },
  go:          { bg: "bg-liquid-teal/40",     text: "text-teal-700 dark:text-teal-300",     label: "GO" },
  rust:        { bg: "bg-liquid-peach/40",    text: "text-orange-700 dark:text-orange-300", label: "RS" },
  yaml:        { bg: "bg-liquid-lime/40",     text: "text-lime-700 dark:text-lime-300",     label: "YAML" },
  json:        { bg: "bg-liquid-lime/40",     text: "text-lime-700 dark:text-lime-300",     label: "JSON" },
  sql:         { bg: "bg-liquid-coral/40",    text: "text-red-700 dark:text-red-300",       label: "SQL" },
  nginx:       { bg: "bg-liquid-teal/40",     text: "text-teal-700 dark:text-teal-300",     label: "NGINX" },
};

function getLangStyle(language: string) {
  return LANG_STYLES[language?.toLowerCase()] ?? {
    bg: "bg-liquid-purple/30",
    text: "text-purple-700 dark:text-purple-300",
    label: language?.toUpperCase() || "CODE",
  };
}

function CodePreview({ code }: { code: string }) {
  const lines = code.split("\n").slice(0, 4);
  return (
    <pre className="mt-4 bg-stone-950/80 rounded-xl p-3 text-[11px] font-mono text-stone-400 overflow-hidden leading-relaxed border border-stone-800/60 select-none">
      {lines.map((line, i) => (
        <div key={i} className="truncate">{line || " "}</div>
      ))}
      {code.split("\n").length > 4 && (
        <div className="text-stone-600 text-[10px] mt-1">…</div>
      )}
    </pre>
  );
}

export default function SnippetsClient({ initialSnippets }: { initialSnippets: Snippet[] }) {
  const [selectedSnippet, setSelectedSnippet] = useState<Snippet | null>(null);
  const [copied, setCopied] = useState(false);
  const [activeCategory, setActiveCategory] = useState<string>("All");
  const [search, setSearch] = useState("");

  // Derived data
  const categories = useMemo(() => {
    const cats = Array.from(new Set(initialSnippets.map((s) => s.category))).sort();
    return ["All", ...cats];
  }, [initialSnippets]);

  const filtered = useMemo(() => {
    const q = search.toLowerCase();
    return initialSnippets.filter((s) => {
      const matchCat = activeCategory === "All" || s.category === activeCategory;
      const matchSearch =
        !q ||
        s.title.toLowerCase().includes(q) ||
        s.description.toLowerCase().includes(q) ||
        s.category.toLowerCase().includes(q) ||
        s.language.toLowerCase().includes(q);
      return matchCat && matchSearch;
    });
  }, [initialSnippets, activeCategory, search]);

  // Language badge for the currently open modal
  const modalLang = useMemo(
    () => (selectedSnippet ? getLangStyle(selectedSnippet.language) : null),
    [selectedSnippet]
  );

  // Keyboard nav: ESC + arrows
  const handleKeyDown = useCallback(
    (e: KeyboardEvent) => {
      if (!selectedSnippet) return;
      if (e.key === "Escape") {
        setSelectedSnippet(null);
      } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
        const idx = filtered.findIndex((s) => s.id === selectedSnippet.id);
        if (idx < filtered.length - 1) setSelectedSnippet(filtered[idx + 1]);
      } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
        const idx = filtered.findIndex((s) => s.id === selectedSnippet.id);
        if (idx > 0) setSelectedSnippet(filtered[idx - 1]);
      }
    },
    [selectedSnippet, filtered]
  );

  useEffect(() => {
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [handleKeyDown]);

  const copyToClipboard = useCallback((code: string) => {
    navigator.clipboard.writeText(code);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  }, []);

  const currentIndex = selectedSnippet
    ? filtered.findIndex((s) => s.id === selectedSnippet.id)
    : -1;

  return (
    <>
      {/* ── Filter & Search bar ── */}
      <div className="flex flex-col sm:flex-row gap-4 mb-10">
        {/* Search */}
        <div className="relative flex-1 max-w-sm">
          <Search size={14} className="absolute left-4 top-1/2 -translate-y-1/2 text-stone-400 pointer-events-none" />
          <input
            type="text"
            placeholder="Search snippets…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="w-full pl-10 pr-4 py-2.5 bg-white dark:bg-stone-900 border border-stone-200 dark:border-stone-800 rounded-2xl text-sm text-stone-900 dark:text-stone-100 placeholder:text-stone-400 focus:outline-none focus:border-liquid-purple transition-colors"
          />
        </div>

        {/* Category chips */}
        <div className="flex flex-wrap gap-2">
          {categories.map((cat) => (
            <button
              key={cat}
              onClick={() => setActiveCategory(cat)}
              className={`px-4 py-2 rounded-2xl text-[11px] font-black uppercase tracking-widest border transition-all ${
                activeCategory === cat
                  ? "bg-stone-900 dark:bg-stone-50 text-white dark:text-stone-900 border-stone-900 dark:border-stone-50 shadow-md"
                  : "bg-white dark:bg-stone-900 text-stone-500 dark:text-stone-400 border-stone-200 dark:border-stone-800 hover:border-liquid-purple hover:text-liquid-purple"
              }`}
            >
              {cat}
            </button>
          ))}
        </div>
      </div>

      {/* ── Empty state ── */}
      {filtered.length === 0 && (
        <p className="text-center text-stone-400 py-24 text-sm">
          No snippets found{search ? ` for "${search}"` : ""}.
        </p>
      )}

      {/* ── Snippet Grid ── */}
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8">
        {filtered.map((s, i) => {
          const lang = getLangStyle(s.language);
          return (
            <motion.button
              key={s.id}
              initial={{ opacity: 0, y: 20 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ delay: i * 0.04 }}
              onClick={() => setSelectedSnippet(s)}
              className="text-left bg-white dark:bg-stone-900 rounded-[2.5rem] p-8 border border-stone-200/60 dark:border-stone-800/60 shadow-sm hover:shadow-xl hover:border-liquid-purple/40 transition-all group flex flex-col"
            >
              {/* Header row: category + language badge */}
              <div className="flex items-center justify-between mb-5">
                <span className="text-[10px] font-black uppercase tracking-widest text-stone-400 group-hover:text-liquid-purple transition-colors">
                  {s.category}
                </span>
                {s.language && (
                  <span className={`px-2.5 py-1 rounded-lg text-[10px] font-black uppercase tracking-wider ${lang.bg} ${lang.text}`}>
                    {lang.label}
                  </span>
                )}
              </div>

              {/* Title */}
              <h3 className="text-xl font-black text-stone-900 dark:text-white uppercase tracking-tighter mb-2 group-hover:text-liquid-purple transition-colors leading-tight">
                {s.title}
              </h3>

              {/* Description */}
              <p className="text-stone-500 dark:text-stone-400 text-sm line-clamp-2 leading-relaxed flex-1">
                {s.description}
              </p>

              {/* Mini code preview */}
              <CodePreview code={s.code} />
            </motion.button>
          );
        })}
      </div>

      {/* ── Snippet Modal ── */}
      <AnimatePresence>
        {selectedSnippet && modalLang && (
          <div className="fixed inset-0 z-[100] flex items-center justify-center p-4 md:p-8">
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              onClick={() => setSelectedSnippet(null)}
              className="absolute inset-0 bg-stone-950/60 backdrop-blur-md"
            />
            <motion.div
              key={selectedSnippet.id}
              initial={{ opacity: 0, scale: 0.95, y: 16 }}
              animate={{ opacity: 1, scale: 1, y: 0 }}
              exit={{ opacity: 0, scale: 0.95, y: 16 }}
              className="relative w-full max-w-3xl bg-white dark:bg-stone-900 rounded-[2.5rem] shadow-2xl border border-stone-200 dark:border-stone-800 overflow-hidden flex flex-col max-h-[90vh]"
            >
              <div className="p-8 md:p-10 overflow-y-auto">
                {/* Modal header */}
                <div className="flex justify-between items-start mb-6">
                  <div className="flex-1 min-w-0 pr-4">
                    <div className="flex items-center gap-3 mb-2 flex-wrap">
                      <p className="text-[10px] font-black uppercase tracking-[0.2em] text-liquid-purple">
                        {selectedSnippet.category}
                      </p>
                      {selectedSnippet.language && (
                        <span className={`px-2.5 py-0.5 rounded-lg text-[10px] font-black uppercase tracking-wider ${modalLang.bg} ${modalLang.text}`}>
                          {modalLang.label}
                        </span>
                      )}
                    </div>
                    <h3 className="text-2xl md:text-3xl font-black text-stone-900 dark:text-white uppercase tracking-tighter leading-tight">
                      {selectedSnippet.title}
                    </h3>
                  </div>
                  <button
                    onClick={() => setSelectedSnippet(null)}
                    className="p-3 bg-stone-50 dark:bg-stone-800 rounded-full hover:bg-stone-100 dark:hover:bg-stone-700 transition-colors shrink-0"
                    title="Close (Esc)"
                  >
                    <X size={20} />
                  </button>
                </div>

                <p className="text-stone-600 dark:text-stone-400 mb-8 leading-relaxed">
                  {selectedSnippet.description}
                </p>

                {/* Code block */}
                <div className="relative">
                  <div className="absolute top-4 right-4 flex gap-2 z-10">
                    <button
                      onClick={() => copyToClipboard(selectedSnippet.code)}
                      className="p-2.5 bg-white/10 backdrop-blur-md hover:bg-white/20 rounded-lg border border-white/10 transition-all text-white"
                      title="Copy code"
                    >
                      {copied ? <Check size={16} className="text-emerald-400" /> : <Copy size={16} />}
                    </button>
                  </div>
                  <pre className="bg-stone-950 p-6 rounded-2xl overflow-x-auto text-sm font-mono text-stone-300 border border-stone-800 leading-relaxed">
                    <code>{selectedSnippet.code}</code>
                  </pre>
                </div>
              </div>

              {/* Modal footer: navigation */}
              <div className="px-8 py-5 bg-stone-50 dark:bg-stone-800/50 border-t border-stone-100 dark:border-stone-800 flex items-center justify-between">
                <button
                  onClick={() => currentIndex > 0 && setSelectedSnippet(filtered[currentIndex - 1])}
                  disabled={currentIndex <= 0}
                  className="flex items-center gap-1.5 text-[10px] font-black uppercase tracking-[0.2em] text-stone-400 hover:text-stone-900 dark:hover:text-white transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
                  title="Previous (←)"
                >
                  <ChevronLeft size={14} /> Prev
                </button>
                <span className="text-[10px] font-black uppercase tracking-[0.2em] text-stone-300 dark:text-stone-600 tabular-nums">
                  {currentIndex + 1} / {filtered.length}
                </span>
                <button
                  onClick={() => currentIndex < filtered.length - 1 && setSelectedSnippet(filtered[currentIndex + 1])}
                  disabled={currentIndex >= filtered.length - 1}
                  className="flex items-center gap-1.5 text-[10px] font-black uppercase tracking-[0.2em] text-stone-400 hover:text-stone-900 dark:hover:text-white transition-colors disabled:opacity-30 disabled:cursor-not-allowed"
                  title="Next (→)"
                >
                  Next <ChevronRight size={14} />
                </button>
              </div>
            </motion.div>
          </div>
        )}
      </AnimatePresence>
    </>
  );
}
