import { useState, useEffect, useMemo, useCallback, useRef } from "react";

// ── Design tokens ──
const T = {
  bg: "#0A0A0C",
  panel: "#141418",
  surface: "#1C1C22",
  border: "#2A2A32",
  amber: "#E8A030",
  amberDim: "#7A5218",
  blue: "#3A7BA8",
  blueDim: "#1E4060",
  green: "#3AB87A",
  red: "#C84040",
  textPrimary: "#F0EDE6",
  textSec: "#8888A0",
  textDim: "#444458",
};

const IMG_PATH = (import.meta.env.BASE_URL || '/ui/') + 'img/';

// ── Category definitions ──
const CATEGORY_DEFS = {
  "Distortions": { icon: "fx_distortion", color: T.red },
  "Dynamics":    { icon: "fx_compressor", color: T.green },
  "Modulations": { icon: "fx_modulator", color: T.blue },
  "Delays":      { icon: "fx_delay", color: "#60A0E0" },
  "Reverbs":     { icon: "fx_reverb", color: "#60C0D0" },
  "Filters":     { icon: "fx_filter", color: "#D0A060" },
  "Amps":        { icon: "fx_amplifier", color: "#E0A040" },
  "Preamps":     { icon: "fx_simulator", color: "#D08040" },
  "Cabs":        { icon: "fx_spatial", color: "#D07090" },
  "IRs":         { icon: "fx_spatial", color: "#70B090" },
  "Pitch/Synth": { icon: "fx_pitch", color: "#A060E0" },
  "Volume/Pan":  { icon: "fx_constant", color: T.textSec },
  "Looper":      { icon: "fx_oscillator", color: "#80D0A0" },
  "Send/Return": { icon: "fx_lr", color: "#9090C0" },
  "Special":     { icon: "fx_utility", color: "#B080C0" },
};

const CATEGORY_ORDER = [
  "Distortions", "Dynamics", "Modulations", "Delays", "Reverbs",
  "Filters", "Amps", "Preamps", "Cabs", "IRs",
  "Pitch/Synth", "Volume/Pan", "Looper", "Send/Return", "Special",
];

const CATEGORY_HIDE = ["Preamps", "Looper", "Pitch/Synth"]; // hide empty categories

// ── Built-in block types mapped to categories ──
const TYPE_TO_CATEGORY = {
  overdrive: "Distortions", disturbance: "Distortions", distortion: "Distortions",
  fuzz: "Distortions", boost: "Distortions", wah: "Filters",
  delay: "Delays", echo: "Delays",
  reverb: "Reverbs",
  chorus: "Modulations", flanger: "Modulations", phaser: "Modulations",
  tremolo: "Modulations", vibrato: "Modulations", rotary: "Modulations",
  compressor: "Dynamics", gate: "Dynamics", limiter: "Dynamics",
  eq: "Filters", filter: "Filters",
  pitch: "Pitch/Synth", harmonizer: "Pitch/Synth", shifter: "Pitch/Synth",
  nam: "Amps", amplifier: "Amps",
  cabinet: "Cabs", cab: "Cabs",
  ir: "IRs",
  volume: "Volume/Pan", level: "Volume/Pan",
  looper: "Looper",
  loop: "Send/Return",
  split: "Special", merge: "Special", tuner: "Special",
  instrument: "Special", plugin: "Special", utility: "Special",
  mixer: "Special", converter: "Special", reamp: "Special",
};

// ── Type-to-color (same palette as BlockChain) ──
const TYPE_COLORS = {
  od: T.amber, overdrive: T.amber, drive: T.amber,
  dist: T.red, distortion: T.red,
  fuzz: "#D060E0",
  mod: T.blue, chorus: T.blue, flange: T.blue, phaser: T.blue,
  tremolo: T.blue, vibrato: T.blue, rotary: T.blue,
  delay: "#60A0E0", echo: "#60A0E0", reverb: "#60C0D0",
  pitch: "#A060E0", comp: T.green, compressor: T.green,
  gate: T.green, filter: "#D0A060", wah: "#D0A060",
  eq: "#80A0B0", ir: T.green, cab: T.green, nam: "#E0A040",
  volume: T.textSec, boost: T.amber,
  split: "#B080C0", merge: "#80B0C0",
};

// ── Type-to-icon map ──
const TYPE_ICON_MAP = {
  od: "fx_distortion", overdrive: "fx_distortion", drive: "fx_distortion",
  dist: "fx_distortion", distortion: "fx_distortion", gain: "fx_distortion",
  fuzz: "fx_distortion",
  delay: "fx_delay", echo: "fx_delay",
  reverb: "fx_reverb",
  chorus: "fx_chorus", flange: "fx_flanger", flanger: "fx_flanger",
  phaser: "fx_phaser", tremolo: "fx_modulator", vibrato: "fx_modulator",
  rotary: "fx_modulator", modulator: "fx_modulator",
  pitch: "fx_pitch", harmonizer: "fx_pitch", shifter: "fx_pitch",
  comp: "fx_compressor", compressor: "fx_compressor",
  limiter: "fx_limiter",
  gate: "fx_gate", noise_gate: "fx_gate",
  filter: "fx_filter", wah: "fx_filter",
  eq: "fx_eq", graphic_eq: "fx_eq",
  parametric_eq: "fx_parametric_eq", multiband_eq: "fx_multiband_eq",
  ir: "fx_spatial", cab: "fx_spatial", cabinet: "fx_spatial",
  nam: "fx_simulator", capture: "fx_simulator", amp: "fx_amplifier",
  amplifier: "fx_amplifier",
  volume: "fx_constant", level: "fx_constant", boost: "fx_constant",
  split: "fx_split_a", merge: "fx_mixer",
  tuner: "fx_analyzer",
  mixer: "fx_mixer", utility: "fx_utility",
  plugin: "fx_plugin",
  instrument: "fx_instrument",
  looper: "fx_oscillator",
  converter: "fx_converter",
  reamp: "fx_converter",
  lr: "fx_lr",
};

// ── Built-in model library ──
const BUILTIN_MODELS = [
  // Distortions
  { type: "overdrive", name: "OD-808",         category: "Distortions", desc: "Classic overdrive" },
  { type: "distortion", name: "RAT",            category: "Distortions", desc: "Aggressive distortion" },
  { type: "fuzz", name: "Big Muff",            category: "Distortions", desc: "Thick fuzz sustain" },
  { type: "boost", name: "Clean Boost",        category: "Distortions", desc: "Clean level boost" },
  // Dynamics
  { type: "compressor", name: "Compressor",    category: "Dynamics",    desc: "Dynamic range control" },
  { type: "gate", name: "Noise Gate",          category: "Dynamics",    desc: "Noise suppression" },
  // Modulations
  { type: "chorus", name: "Chorus",            category: "Modulations", desc: "Rich chorus effect" },
  { type: "flanger", name: "Flanger",          category: "Modulations", desc: "Jet plane sweep" },
  { type: "phaser", name: "Phase 90",          category: "Modulations", desc: "Iconic phase shift" },
  { type: "tremolo", name: "Tremolo",          category: "Modulations", desc: "Volume modulation" },
  // Delays
  { type: "delay", name: "Digital Delay",      category: "Delays",      desc: "Clean digital repeats" },
  { type: "echo", name: "Tape Echo",           category: "Delays",      desc: "Warm tape repeats" },
  // Reverbs
  { type: "reverb", name: "Hall Reverb",       category: "Reverbs",     desc: "Lush hall reverb" },
  // Filters
  { type: "eq", name: "Equalizer",            category: "Filters",     desc: "3-band tone control" },
  { type: "wah", name: "Wah",                  category: "Filters",     desc: "Crybaby wah" },
  // Volume/Pan
  { type: "volume", name: "Volume Pedal",      category: "Volume/Pan",  desc: "Volume control" },
  // Special
  { type: "split", name: "Split",              category: "Special",     desc: "Parallel routing" },
  { type: "merge", name: "Merge",              category: "Special",     desc: "Sum parallel paths" },
  { type: "tuner", name: "Tuner",              category: "Special",     desc: "Instrument tuner" },
  { type: "loop", name: "FX Loop",             category: "Send/Return", desc: "External FX send/return" },
  // Cabs & IRs
  { type: "cabinet", name: "Cabinet",          category: "Cabs",        desc: "Speaker cabinet sim" },
  { type: "ir", name: "IR Loader",             category: "IRs",         desc: "Impulse response loader" },
  // Amps
  { type: "nam", name: "NAM Model",            category: "Amps",        desc: "Neural amp model" },
];

// ── Helper: resolve icon for a type ──
function getIconFile(type) {
  const key = (type || "").toLowerCase().trim();
  for (const [k, v] of Object.entries(TYPE_ICON_MAP)) {
    if (key === k || key.startsWith(k) || key.includes(k)) return v;
  }
  return "fx_plugin";
}

function getTypeColor(type) {
  const key = (type || "").toLowerCase().trim();
  for (const [k, v] of Object.entries(TYPE_COLORS)) {
    if (key === k || key.startsWith(k) || key.includes(k)) return v;
  }
  return T.amber;
}

// ── Block Icon (inline from BlockChain) ──
function BlockIcon({ type, size = 16 }) {
  const icon = getIconFile(type);
  return (
    <img
      src={`${IMG_PATH}${icon}.svg`}
      alt={type || "fx"}
      style={{
        width: size, height: size, flexShrink: 0,
        filter: "invert(0.95) brightness(2)",
        objectFit: "contain",
      }}
      onError={(e) => { e.target.style.display = "none"; }}
    />
  );
}

// ── Category Icon ──
function CategoryIcon({ category, size = 14 }) {
  const def = CATEGORY_DEFS[category];
  if (!def) return null;
  return (
    <img
      src={`${IMG_PATH}${def.icon}.svg`}
      alt={category}
      style={{
        width: size, height: size, flexShrink: 0,
        filter: "invert(0.95) brightness(2)",
        objectFit: "contain",
      }}
      onError={(e) => { e.target.style.display = "none"; }}
    />
  );
}

// ── Model Browser ──
export default function ModelBrowser({
  currentBlockType,
  currentBlockName,
  currentModelPath,
  onSelectModel,
  onClose,
}) {
  const [activeTab, setActiveTab] = useState("All");
  const [searchQuery, setSearchQuery] = useState("");
  const [loadedModels, setLoadedModels] = useState([]);
  const [favorites, setFavorites] = useState(() => {
    try {
      const saved = localStorage.getItem("helix_model_favorites");
      return saved ? JSON.parse(saved) : [];
    } catch { return []; }
  });
  const searchRef = useRef(null);

  // Load installed NAM / IR models from API
  useEffect(() => {
    let cancelled = false;
    const load = async () => {
      try {
        const data = await fetch("/api/models").then(r => r.json());
        if (!cancelled) setLoadedModels(data.models || []);
      } catch {}
    };
    load();
    return () => { cancelled = true; };
  }, []);

  // Save favorites
  const toggleFav = useCallback((id) => {
    setFavorites(prev => {
      const next = prev.includes(id) ? prev.filter(f => f !== id) : [...prev, id];
      localStorage.setItem("helix_model_favorites", JSON.stringify(next));
      return next;
    });
  }, []);

  // ── Determine current model ID for highlight ──
  const currentModelId = currentModelPath
    ? currentModelPath
    : currentBlockType
    ? `builtin:${currentBlockType}`
    : null;

  // ── Build model list ──
  const allModels = useMemo(() => {
    const list = [];

    // Built-in block types
    for (const m of BUILTIN_MODELS) {
      list.push({
        id: `builtin:${m.type}`,
        type: m.type,
        name: m.name,
        category: m.category,
        desc: m.desc,
        isBuiltin: true,
        iconType: m.type,
      });
    }

    // Installed NAM models — map to Amps category
    for (const m of loadedModels) {
      const label = m.name || m.filename || "Unnamed Model";
      list.push({
        id: `nam:${label}`,
        type: "nam",
        name: label,
        category: "Amps",
        desc: m.architecture ? `${m.architecture} · ${m.size_mb}MB` : "Installed NAM model",
        isBuiltin: false,
        loaded: m.loaded,
        modelPath: m.path || m.filename,
        iconType: "nam",
      });
    }

    return list;
  }, [loadedModels]);

  // ── Filter by tab & search ──
  const visibleCategories = useMemo(() => {
    if (activeTab === "All") {
      const cats = [...CATEGORY_ORDER];
      // Only show non-empty + visible categories
      return cats.filter(c => {
        if (CATEGORY_HIDE.includes(c)) {
          // Only show hidden categories if they have installed models
          return allModels.some(m => m.category === c && !m.isBuiltin);
        }
        return allModels.some(m => m.category === c);
      });
    }
    if (activeTab === "★Favorites") return [];
    return [activeTab];
  }, [activeTab, allModels]);

  const filteredModels = useMemo(() => {
    let list = allModels;

    // Tab filter
    if (activeTab === "★Favorites") {
      list = list.filter(m => favorites.includes(m.id));
    } else if (activeTab !== "All") {
      list = list.filter(m => m.category === activeTab);
    }

    // Search filter
    if (searchQuery.trim()) {
      const q = searchQuery.toLowerCase();
      list = list.filter(m =>
        m.name.toLowerCase().includes(q) ||
        m.type.toLowerCase().includes(q) ||
        (m.desc || "").toLowerCase().includes(q) ||
        (m.category || "").toLowerCase().includes(q)
      );
    }

    return list;
  }, [allModels, activeTab, searchQuery, favorites]);

  const groupedByCategory = useMemo(() => {
    if (activeTab !== "All" && activeTab !== "★Favorites") return null;
    const groups = {};
    for (const m of filteredModels) {
      if (!groups[m.category]) groups[m.category] = [];
      groups[m.category].push(m);
    }
    return groups;
  }, [filteredModels, activeTab]);

  // ── Handle model selection ──
  const handleSelect = useCallback((model) => {
    onSelectModel?.({
      type: model.type,
      name: model.name,
      modelPath: model.isBuiltin ? null : model.modelPath || model.id,
      isBuiltin: model.isBuiltin,
    });
    onClose?.();
  }, [onSelectModel, onClose]);

  // ── Handle tab selection ──
  const tabs = ["All", "★Favorites", ...CATEGORY_ORDER.filter(c => {
    // Only show categories that have models
    if (CATEGORY_HIDE.includes(c)) {
      return allModels.some(m => m.category === c && !m.isBuiltin);
    }
    return allModels.some(m => m.category === c);
  })];

  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 1000,
      display: "flex", flexDirection: "column",
      background: T.bg,
      color: T.textPrimary,
      fontFamily: "'Inter', sans-serif",
    }}>
      {/* ── Header ── */}
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "10px 14px",
        borderBottom: `1px solid ${T.border}`,
        background: T.panel,
        flexShrink: 0,
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <button onClick={onClose}
            style={{
              width: 34, height: 34, borderRadius: 8,
              display: "flex", alignItems: "center", justifyContent: "center",
              background: T.surface, border: `1px solid ${T.border}`,
              color: T.textPrimary, fontSize: 16, cursor: "pointer",
            }}>
            ✕
          </button>
          <div>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Model Browser</div>
            {currentBlockName && (
              <div style={{ fontSize: 10, color: T.textSec, marginTop: 1 }}>
                Current: {currentBlockName}
              </div>
            )}
          </div>
        </div>
      </div>

      {/* ── Search bar ── */}
      <div style={{
        padding: "8px 14px",
        borderBottom: `1px solid ${T.border}`,
        background: T.surface,
        flexShrink: 0,
      }}>
        <div style={{
          display: "flex", alignItems: "center", gap: 8,
          background: T.panel, borderRadius: 7,
          border: `1px solid ${T.border}`,
          padding: "7px 10px",
        }}>
          <span style={{ color: T.textDim, fontSize: 13 }}>🔍</span>
          <input
            ref={searchRef}
            placeholder="Search models..."
            value={searchQuery}
            onChange={e => setSearchQuery(e.target.value)}
            style={{
              flex: 1, background: "none", border: "none",
              color: T.textPrimary, fontSize: 13, outline: "none",
            }}
          />
          {searchQuery && (
            <button onClick={() => setSearchQuery("")}
              style={{
                background: "none", border: "none", color: T.textDim,
                fontSize: 14, cursor: "pointer", padding: 2,
              }}>
              ✕
            </button>
          )}
        </div>
      </div>

      {/* ── Category tabs ── */}
      <div style={{
        display: "flex", gap: 0,
        overflowX: "auto", overflowY: "hidden",
        borderBottom: `1px solid ${T.border}`,
        background: T.panel,
        flexShrink: 0,
        WebkitOverflowScrolling: "touch",
      }}>
        {tabs.map(tab => {
          const def = CATEGORY_DEFS[tab];
          const isActive = activeTab === tab;
          return (
            <button key={tab} onClick={() => setActiveTab(tab)}
              style={{
                padding: "8px 12px",
                fontSize: 10, fontWeight: 600,
                letterSpacing: ".04em",
                whiteSpace: "nowrap",
                background: "none",
                border: "none",
                borderBottom: `2px solid ${isActive ? T.amber : "transparent"}`,
                color: isActive ? T.textPrimary : T.textSec,
                cursor: "pointer",
                display: "flex", alignItems: "center", gap: 5,
                flexShrink: 0,
                transition: "all .12s",
              }}>
              {def && <CategoryIcon category={tab} size={12} />}
              {tab === "★Favorites" && <span>★</span>}
              {tab === "★Favorites" ? " Favorites" : tab}
            </button>
          );
        })}
      </div>

      {/* ── Model grid area ── */}
      <div style={{
        flex: 1, overflowY: "auto", overflowX: "hidden",
        padding: "10px 14px",
        WebkitOverflowScrolling: "touch",
      }}>
        {/* Favorites empty state */}
        {activeTab === "★Favorites" && filteredModels.length === 0 && (
          <div style={{
            display: "flex", flexDirection: "column", alignItems: "center",
            justifyContent: "center", padding: "40px 20px", gap: 8,
            color: T.textDim,
          }}>
            <span style={{ fontSize: 28 }}>☆</span>
            <div style={{ fontSize: 13, fontWeight: 500 }}>No favorites yet</div>
            <div style={{ fontSize: 11, textAlign: "center" }}>
              Star a model to add it to your favorites
            </div>
          </div>
        )}

        {/* Search empty state */}
        {searchQuery && filteredModels.length === 0 && (
          <div style={{
            display: "flex", flexDirection: "column", alignItems: "center",
            justifyContent: "center", padding: "40px 20px", gap: 8,
            color: T.textDim,
          }}>
            <div style={{ fontSize: 13 }}>No models matching "{searchQuery}"</div>
          </div>
        )}

        {/* Categories with models (All tab) or just the models */}
        {groupedByCategory ? (
          // All tab — grouped by category
          visibleCategories.map(cat => {
            const models = groupedByCategory[cat] || [];
            if (models.length === 0) return null;
            const def = CATEGORY_DEFS[cat];
            return (
              <div key={cat} style={{ marginBottom: 20 }}>
                <div style={{
                  display: "flex", alignItems: "center", gap: 8,
                  marginBottom: 8,
                }}>
                  {def && <CategoryIcon category={cat} size={16} />}
                  <span style={{
                    fontSize: 11, fontWeight: 700, letterSpacing: ".08em",
                    textTransform: "uppercase", color: T.textSec,
                  }}>{cat}</span>
                  <div style={{
                    flex: 1, height: 1, background: T.border, opacity: 0.4,
                  }} />
                </div>
                <div style={{
                  display: "grid",
                  gridTemplateColumns: "repeat(auto-fill, minmax(130px, 1fr))",
                  gap: 6,
                }}>
                  {models.map(model => (
                    <ModelTile
                      key={model.id}
                      model={model}
                      isCurrent={model.id === currentModelId}
                      isFavorite={favorites.includes(model.id)}
                      onSelect={() => handleSelect(model)}
                      onToggleFav={() => toggleFav(model.id)}
                    />
                  ))}
                </div>
              </div>
            );
          })
        ) : (
          // Specific tab — flat grid
          <>
            {filteredModels.length > 0 && (
              <div style={{
                display: "grid",
                gridTemplateColumns: "repeat(auto-fill, minmax(130px, 1fr))",
                gap: 6,
              }}>
                {filteredModels.map(model => (
                  <ModelTile
                    key={model.id}
                    model={model}
                    isCurrent={model.id === currentModelId}
                    isFavorite={favorites.includes(model.id)}
                    onSelect={() => handleSelect(model)}
                    onToggleFav={() => toggleFav(model.id)}
                  />
                ))}
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

// ── Individual Model Tile ──
function ModelTile({ model, isCurrent, isFavorite, onSelect, onToggleFav }) {
  const color = getTypeColor(model.type);
  const [imgError, setImgError] = useState(false);

  return (
    <div onClick={onSelect}
      style={{
        display: "flex", flexDirection: "column", gap: 0,
        padding: "10px 8px 8px",
        borderRadius: 8,
        background: isCurrent
          ? `linear-gradient(135deg, ${color}18, ${T.panel})`
          : T.surface,
        border: `1.5px solid ${isCurrent ? color + "66" : T.border}`,
        cursor: "pointer",
        position: "relative",
        transition: "all .12s",
        boxShadow: isCurrent ? `0 0 12px ${color}33` : "none",
        minHeight: 72,
      }}
    >
      {/* Favorite star */}
      <div onClick={(e) => { e.stopPropagation(); onToggleFav(); }}
        style={{
          position: "absolute", top: 4, right: 4,
          fontSize: 13, cursor: "pointer", zIndex: 2,
          color: isFavorite ? T.amber : T.textDim,
          textShadow: isFavorite ? `0 0 4px ${T.amber}` : "none",
          transition: "all .15s",
          lineHeight: 1,
        }}>
        {isFavorite ? "★" : "☆"}
      </div>

      {/* Model icon */}
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "center",
        height: 34, marginBottom: 6,
      }}>
        {!imgError ? (
          <img
            src={`${IMG_PATH}${getIconFile(model.iconType || model.type)}.svg`}
            alt={model.type}
            style={{
              width: 28, height: 28,
              filter: `invert(0.95) brightness(2) drop-shadow(0 0 4px ${color}44)`,
              objectFit: "contain",
            }}
            onError={() => setImgError(true)}
          />
        ) : (
          <span style={{
            fontSize: 18, color, opacity: 0.7,
            fontFamily: "'JetBrains Mono', monospace", fontWeight: 700,
          }}>
            {model.name.charAt(0)}
          </span>
        )}
      </div>

      {/* Model name */}
      <div style={{
        fontSize: 11, fontWeight: 600,
        color: isCurrent ? color : T.textPrimary,
        textAlign: "center",
        whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
        lineHeight: 1.3,
      }}>
        {model.name}
      </div>

      {/* Type badge */}
      <div style={{
        display: "flex", justifyContent: "center", marginTop: 3,
      }}>
        <span style={{
          display: "inline-flex", padding: "1px 5px", borderRadius: 3,
          fontSize: 8, fontWeight: 700, letterSpacing: ".05em",
          textTransform: "uppercase",
          background: `${color}18`, color,
        }}>
          {model.type.replace(/_/g, " ")}
        </span>
      </div>

      {/* Description */}
      {model.desc && (
        <div style={{
          fontSize: 8, color: T.textDim,
          textAlign: "center", marginTop: 3,
          whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
        }}>
          {model.desc}
        </div>
      )}

      {/* Current indicator */}
      {isCurrent && (
        <div style={{
          position: "absolute", top: 4, left: 4,
          width: 6, height: 6, borderRadius: "50%",
          background: T.green,
          boxShadow: `0 0 6px ${T.green}`,
        }} />
      )}
    </div>
  );
}
