import { useState, useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import api from "../../api/client";
import { useAuth } from "../../auth/AuthContext";

const inputStyle = {
  backgroundColor: "var(--bg-input)",
  borderColor: "var(--border-primary)",
  color: "var(--text-primary)",
};

const TITLE_SHORT = {
  "Fr.": "Fr.", "Rev.": "Rev.", "Archim.": "Archim.", "Bp.": "Bp.",
  "Abp.": "Abp.", "Met.": "Met.", "Mr.": "Mr.", "Mrs.": "Mrs.",
  "Ms.": "Ms.", "Dr.": "Dr.", "Prof.": "Prof.",
};

// ISO 639-1 → human-readable. Extend as needed.
const LANGUAGE_NAMES = {
  af: "Afrikaans", sq: "Albanian", am: "Amharic", ar: "Arabic",
  hy: "Armenian", az: "Azerbaijani", eu: "Basque", be: "Belarusian",
  bn: "Bengali", bs: "Bosnian", bg: "Bulgarian", ca: "Catalan",
  zh: "Chinese", hr: "Croatian", cs: "Czech", da: "Danish",
  nl: "Dutch", en: "English", et: "Estonian", fi: "Finnish",
  fr: "French", ka: "Georgian", de: "German", el: "Greek",
  gu: "Gujarati", he: "Hebrew", hi: "Hindi", hu: "Hungarian",
  id: "Indonesian", it: "Italian", ja: "Japanese", kn: "Kannada",
  kk: "Kazakh", ko: "Korean", lv: "Latvian", lt: "Lithuanian",
  mk: "Macedonian", ms: "Malay", ml: "Malayalam", mt: "Maltese",
  mr: "Marathi", mn: "Mongolian", ne: "Nepali", no: "Norwegian",
  fa: "Persian", pl: "Polish", pt: "Portuguese", pa: "Punjabi",
  ro: "Romanian", ru: "Russian", sr: "Serbian", si: "Sinhala",
  sk: "Slovak", sl: "Slovenian", es: "Spanish", sw: "Swahili",
  sv: "Swedish", tl: "Tagalog", ta: "Tamil", te: "Telugu",
  th: "Thai", tr: "Turkish", uk: "Ukrainian", ur: "Urdu",
  uz: "Uzbek", vi: "Vietnamese", cy: "Welsh", yi: "Yiddish",
  zu: "Zulu",
};

function resolveLanguage(val) {
  if (!val) return "—";
  const key = val.trim().toLowerCase();
  return LANGUAGE_NAMES[key] || val;
}

const ALL_COLUMNS = [
  { id: "name",         label: "Name",          default: true,  locked: true  },
  { id: "status",       label: "Status",        default: true  },
  { id: "organization", label: "Organization",  default: true  },
  { id: "address",      label: "Full Address",  default: true  },
  { id: "location",     label: "Location",      default: true  },
  { id: "email",        label: "Email",         default: true  },
  { id: "phone",        label: "Phone",         default: true  },
  { id: "tags",         label: "Tags",          default: true  },
  { id: "religion",     label: "Religion",      default: false },
  { id: "language",     label: "Language",      default: false },
];

const SORT_OPTIONS = [
  { value: "default",     label: "Date Added" },
  { value: "name",        label: "First Name" },
  { value: "surname",     label: "Surname" },
  { value: "latest_comm", label: "Latest Communication" },
];

const COL_STORAGE_KEY   = "crm_customers_columns";
const COL_ORDER_KEY     = "crm_customers_col_order";
const NOTES_MODE_KEY    = "crm_customers_notes_mode";

function loadColumnPrefs() {
  try {
    const vis   = JSON.parse(localStorage.getItem(COL_STORAGE_KEY) || "null");
    const order = JSON.parse(localStorage.getItem(COL_ORDER_KEY)   || "null");
    const visible    = vis   || Object.fromEntries(ALL_COLUMNS.map((c) => [c.id, c.default]));
    const orderedIds = order || ALL_COLUMNS.map((c) => c.id);
    for (const c of ALL_COLUMNS) {
      if (!orderedIds.includes(c.id)) orderedIds.push(c.id);
    }
    const filtered = orderedIds.filter(id => ALL_COLUMNS.find(c => c.id === id));
    // Always force locked columns visible
    for (const c of ALL_COLUMNS) {
      if (c.locked) visible[c.id] = true;
    }
    return { visible, orderedIds: filtered };
  } catch {
    return {
      visible:    Object.fromEntries(ALL_COLUMNS.map((c) => [c.id, c.default])),
      orderedIds: ALL_COLUMNS.map((c) => c.id),
    };
  }
}

function saveColumnPrefs(visible, orderedIds) {
  localStorage.setItem(COL_STORAGE_KEY, JSON.stringify(visible));
  localStorage.setItem(COL_ORDER_KEY,   JSON.stringify(orderedIds));
}

// ── Inline SVG icon components (currentColor, no hardcoded fills) ──────────

function IconNegotiations({ style }) {
  return (
    <svg style={style} viewBox="0 -8 72 72" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
      <path d="M64,12.78v17s-3.63.71-4.38.81-3.08.85-4.78-.78C52.22,27.25,42.93,18,42.93,18a3.54,3.54,0,0,0-4.18-.21c-2.36,1.24-5.87,3.07-7.33,3.78a3.37,3.37,0,0,1-5.06-2.64,3.44,3.44,0,0,1,2.1-3c3.33-2,10.36-6,13.29-7.52,1.78-1,3.06-1,5.51,1C50.27,12,53,14.27,53,14.27a2.75,2.75,0,0,0,2.26.43C58.63,14,64,12.78,64,12.78ZM27,41.5a3,3,0,0,0-3.55-4.09,3.07,3.07,0,0,0-.64-3,3.13,3.13,0,0,0-3-.75,3.07,3.07,0,0,0-.65-3,3.38,3.38,0,0,0-4.72.13c-1.38,1.32-2.27,3.72-1,5.14s2.64.55,3.72.3c-.3,1.07-1.2,2.07-.09,3.47s2.64.55,3.72.3c-.3,1.07-1.16,2.16-.1,3.46s2.84.61,4,.25c-.45,1.15-1.41,2.39-.18,3.79s4.08.75,5.47-.58a3.32,3.32,0,0,0,.3-4.68A3.18,3.18,0,0,0,27,41.5Zm25.35-8.82L41.62,22a3.53,3.53,0,0,0-3.77-.68c-1.5.66-3.43,1.56-4.89,2.24a8.15,8.15,0,0,1-3.29,1.1,5.59,5.59,0,0,1-3-10.34C29,12.73,34.09,10,34.09,10a6.46,6.46,0,0,0-5-2C25.67,8,18.51,12.7,18.51,12.7a5.61,5.61,0,0,1-4.93.13L8,10.89v19.4s1.59.46,3,1a6.33,6.33,0,0,1,1.56-2.47,6.17,6.17,0,0,1,8.48-.06,5.4,5.4,0,0,1,1.34,2.37,5.49,5.49,0,0,1,2.29,1.4A5.4,5.4,0,0,1,26,34.94a5.47,5.47,0,0,1,3.71,4,5.38,5.38,0,0,1,2.39,1.43,5.65,5.65,0,0,1,1.48,4.89,0,0,0,0,1,0,0s.8.9,1.29,1.39a2.46,2.46,0,0,0,3.48-3.48s2,2.48,4.28,1c2-1.4,1.69-3.06.74-4a3.19,3.19,0,0,0,4.77.13,2.45,2.45,0,0,0,.13-3.3s1.33,1.81,4,.12c1.89-1.6,1-3.43,0-4.39Z"/>
    </svg>
  );
}

function IconIssues({ style }) {
  return (
    <svg style={style} viewBox="0 0 283.722 283.722" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
      <path d="M184.721,128.156c4.398-14.805,7.516-29.864,8.885-43.783c0.06-0.607-0.276-1.159-0.835-1.373l-70.484-26.932c-0.152-0.058-0.312-0.088-0.475-0.088c-0.163,0-0.322,0.03-0.474,0.088L50.851,83c-0.551,0.21-0.894,0.775-0.835,1.373c2.922,29.705,13.73,64.62,28.206,91.12c14.162,25.923,30.457,41.4,43.589,41.4c8.439,0,18.183-6.4,27.828-17.846l-16.375-16.375c-14.645-14.645-14.645-38.389,0-53.033C147.396,115.509,169.996,115.017,184.721,128.156z"/>
      <path d="M121.812,236.893c-46.932,0-85.544-87.976-91.7-150.562c-0.94-9.56,4.627-18.585,13.601-22.013l70.486-26.933c2.451-0.937,5.032-1.405,7.613-1.405c2.581,0,5.162,0.468,7.614,1.405l70.484,26.932c8.987,3.434,14.542,12.439,13.6,22.013c-1.773,18.028-6.244,38.161-12.826,57.693l11.068,11.068l17.865-17.866c6.907-20.991,11.737-42.285,13.845-61.972c1.322-12.347-5.53-24.102-16.934-29.017l-93.512-40.3c-7.152-3.082-15.257-3.082-22.409,0l-93.512,40.3C5.705,51.147-1.159,62.922,0.162,75.255c8.765,81.851,64.476,191.512,121.65,191.512c0.356,0,0.712-0.023,1.068-0.032c-1.932-10.793,0.888-22.262,8.456-31.06C128.205,236.465,125.029,236.893,121.812,236.893z"/>
      <path d="M240.037,208.125c7.327-7.326,30.419-30.419,37.827-37.827c7.81-7.811,7.81-20.475,0-28.285c-7.811-7.811-20.475-7.811-28.285,0c-7.41,7.41-30.5,30.5-37.827,37.827l-37.827-37.827c-7.81-7.811-20.475-7.811-28.285,0c-7.811,7.811-7.811,20.475,0,28.285l37.827,37.827c-7.326,7.326-30.419,30.419-37.827,37.827c-7.811,7.811-7.811,20.475,0,28.285c7.809,7.809,20.474,7.811,28.285,0c7.41-7.41,30.5-30.499,37.827-37.827l37.827,37.827c7.809,7.809,20.474,7.811,28.285,0c7.81-7.81,7.81-20.475,0-28.285L240.037,208.125z"/>
    </svg>
  );
}

function IconImportant({ style, className }) {
  return (
    <svg style={style} className={className} viewBox="0 0 299.467 299.467" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
      <path d="M293.588,219.182L195.377,32.308c-8.939-17.009-26.429-27.575-45.644-27.575s-36.704,10.566-45.644,27.575L5.879,219.182c-8.349,15.887-7.77,35.295,1.509,50.647c9.277,15.36,26.189,24.903,44.135,24.903h196.422c17.943,0,34.855-9.542,44.133-24.899C301.357,254.477,301.936,235.069,293.588,219.182z M266.4,254.319c-3.881,6.424-10.953,10.414-18.456,10.414H51.522c-7.505,0-14.576-3.99-18.457-10.417c-3.88-6.419-4.121-14.534-0.63-21.177l98.211-186.876c3.737-7.112,11.052-11.531,19.087-11.531s15.35,4.418,19.087,11.531l98.211,186.876C270.522,239.782,270.281,247.897,266.4,254.319z"/>
      <polygon points="144.037,201.424 155.429,201.424 166.545,87.288 132.92,87.288"/>
      <path d="M149.733,212.021c-8.98,0-16.251,7.272-16.251,16.252c0,8.971,7.271,16.251,16.251,16.251c8.979,0,16.251-7.28,16.251-16.251C165.984,219.294,158.713,212.021,149.733,212.021z"/>
    </svg>
  );
}

// ── Status icons helpers ─────────────────────────────────────────────────────

function statusColors(direction) {
  const pendingOurReply = direction === "inbound";
  // negotiations: yellow if we sent last, orange if client sent last
  // issues: yellow if we sent last, red if client sent last
  const negColor = pendingOurReply ? "var(--crm-status-alert)" : "#e8a504";
  const issColor = pendingOurReply ? "var(--crm-status-danger)" : "#e03535";
  return { negColor, issColor, pendingOurReply };
}

// ── Quick mode status cell ───────────────────────────────────────────────────
// Icon sizes — edit these to adjust icon dimensions per mode:
//   Quick mode icons: QUICK_ICON_SIZE (negotiations slightly larger than issues)
const QUICK_NEG_ICON_SIZE  = 25; // px — negotiations icon in Quick mode
const QUICK_ISS_ICON_SIZE  = 20; // px — issues icon in Quick mode
const QUICK_IMP_ICON_SIZE  = 17; // px — exclamation icon in Quick mode
//   Expanded sub-row icons:
const EXP_NEG_ICON_SIZE    = 22; // px — negotiations icon in Expanded sub-rows
const EXP_ISS_ICON_SIZE    = 16; // px — issues icon in Expanded sub-rows
const EXP_IMP_ICON_SIZE    = 12; // px — exclamation icon in Expanded sub-rows

function StatusIconsCell({ customer, direction }) {
  const hasNeg = customer.negotiating;
  const hasIssue = customer.has_problem;
  if (!hasNeg && !hasIssue) return <td className="px-3 py-3" />;

  const { negColor, issColor, pendingOurReply } = statusColors(direction);

  return (
    <td className="px-3 py-3" style={{ textAlign: "center" }}>
      <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
        {hasNeg && (
          <span
            title={pendingOurReply ? "Negotiating — client awaiting our reply" : "Negotiating — we sent last"}
            style={{ color: negColor, display: "inline-flex" }}
          >
            <IconNegotiations style={{ width: QUICK_NEG_ICON_SIZE, height: QUICK_NEG_ICON_SIZE, display: "inline-block", flexShrink: 0 }} />
          </span>
        )}
        {hasIssue && (
          <span
            title={pendingOurReply ? "Open issue — client awaiting our reply" : "Open issue — we last contacted them"}
            style={{ color: issColor, display: "inline-flex" }}
          >
            <IconIssues style={{ width: QUICK_ISS_ICON_SIZE, height: QUICK_ISS_ICON_SIZE, display: "inline-block", flexShrink: 0 }} />
          </span>
        )}
        {(hasNeg || hasIssue) && pendingOurReply && (
          <span title="Awaiting our reply" style={{ color: "var(--crm-status-alert)", display: "inline-flex" }}>
            <IconImportant style={{ width: QUICK_IMP_ICON_SIZE, height: QUICK_IMP_ICON_SIZE, display: "inline-block", flexShrink: 0 }} className="crm-icon-breathe" />
          </span>
        )}
      </div>
    </td>
  );
}

// ── Original inline icons (small, in name cell) ──────────────────────────────

function relDays(dateStr) {
  if (!dateStr) return null;
  const d = new Date(dateStr);
  if (isNaN(d)) return null;
  const days = Math.floor((Date.now() - d.getTime()) / 86400000);
  if (days === 0) return "today";
  if (days === 1) return "yesterday";
  return `${days} days ago`;
}

// ── Column toggle ────────────────────────────────────────────────────────────

function ColumnToggle({ visible, orderedIds, onChange, onReorder }) {
  const [open, setOpen] = useState(false);
  const [dragging, setDragging] = useState(null);
  const ref = useRef(null);

  useEffect(() => {
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const handleDragOver = (e, id) => {
    e.preventDefault();
    if (dragging && dragging !== id) {
      const next = [...orderedIds];
      const from = next.indexOf(dragging);
      const to   = next.indexOf(id);
      next.splice(from, 1);
      next.splice(to, 0, dragging);
      onReorder(next);
    }
  };

  const visibleCount = Object.values(visible).filter(Boolean).length;

  return (
    <div style={{ position: "relative" }} ref={ref}>
      <button
        onClick={() => setOpen((v) => !v)}
        className="flex items-center gap-1.5 px-3 py-2 text-sm rounded-md border hover:opacity-80 cursor-pointer transition-opacity"
        style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-primary)", color: "var(--text-secondary)" }}
      >
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
        </svg>
        Columns ({visibleCount})
      </button>
      {open && (
        <div style={{ position: "absolute", right: 0, top: "calc(100% + 4px)", zIndex: 20, backgroundColor: "var(--bg-card)", border: "1px solid var(--border-primary)", borderRadius: 8, width: 200, boxShadow: "0 8px 24px rgba(0,0,0,0.15)", padding: 8 }}>
          <p className="text-xs font-medium px-2 py-1 mb-1" style={{ color: "var(--text-muted)" }}>
            Drag to reorder · Click to toggle
          </p>
          {orderedIds.map((id) => {
            const col = ALL_COLUMNS.find((c) => c.id === id);
            if (!col) return null;
            const isLocked = !!col.locked;
            return (
              <div
                key={id}
                draggable={!isLocked}
                onDragStart={() => !isLocked && setDragging(id)}
                onDragOver={(e) => handleDragOver(e, id)}
                onDragEnd={() => setDragging(null)}
                onClick={() => !isLocked && onChange(id, !visible[id])}
                style={{
                  display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", borderRadius: 6,
                  cursor: isLocked ? "default" : "pointer", userSelect: "none",
                  backgroundColor: dragging === id ? "var(--bg-card-hover)" : "transparent",
                  opacity: isLocked ? 0.5 : 1,
                }}
                onMouseEnter={(e) => { if (!isLocked) e.currentTarget.style.backgroundColor = "var(--bg-card-hover)"; }}
                onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = dragging === id ? "var(--bg-card-hover)" : "transparent"; }}
              >
                <span style={{ fontSize: 11, color: "var(--text-muted)", cursor: isLocked ? "default" : "grab" }}>⠿</span>
                <div style={{
                  width: 14, height: 14, borderRadius: 3,
                  border: `2px solid ${isLocked ? "var(--border-primary)" : visible[id] ? "var(--accent)" : "var(--border-primary)"}`,
                  backgroundColor: isLocked ? "var(--border-primary)" : visible[id] ? "var(--accent)" : "transparent",
                  display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
                }}>
                  {(isLocked || visible[id]) && <span style={{ color: "#fff", fontSize: 9, lineHeight: 1 }}>✓</span>}
                </div>
                <span className="text-xs" style={{ color: "var(--text-primary)" }}>
                  {col.label}{isLocked ? " (locked)" : ""}
                </span>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ── Filter dropdown ──────────────────────────────────────────────────────────

const FILTER_OPTIONS = [
  { value: "negotiating",  label: "Negotiating" },
  { value: "has_problem",  label: "Has Open Issue" },
];

function FilterDropdown({ active, onChange }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const toggle = (value) => {
    const next = new Set(active);
    if (next.has(value)) next.delete(value); else next.add(value);
    onChange(next);
  };

  const count = active.size;

  return (
    <div style={{ position: "relative" }} ref={ref}>
      <button
        onClick={() => setOpen(v => !v)}
        className="flex items-center gap-1.5 px-3 py-2 text-sm rounded-md border hover:opacity-80 cursor-pointer transition-opacity"
        style={{
          backgroundColor: count > 0 ? "var(--accent)" : "var(--bg-input)",
          borderColor: count > 0 ? "var(--accent)" : "var(--border-primary)",
          color: count > 0 ? "#fff" : "var(--text-secondary)",
          whiteSpace: "nowrap",
        }}
      >
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2a1 1 0 01-.293.707L13 13.414V19a1 1 0 01-.553.894l-4 2A1 1 0 017 21v-7.586L3.293 6.707A1 1 0 013 6V4z" />
        </svg>
        Filter{count > 0 ? ` (${count})` : ""}
      </button>
      {open && (
        <div style={{
          position: "absolute", right: 0, top: "calc(100% + 4px)", zIndex: 20,
          backgroundColor: "var(--bg-card)", border: "1px solid var(--border-primary)",
          borderRadius: 8, minWidth: 190, boxShadow: "0 8px 24px rgba(0,0,0,0.15)", overflow: "hidden",
        }}>
          {FILTER_OPTIONS.map(opt => {
            const checked = active.has(opt.value);
            return (
              <button
                key={opt.value}
                onClick={() => toggle(opt.value)}
                style={{
                  display: "flex", alignItems: "center", gap: 10, width: "100%", textAlign: "left",
                  padding: "9px 14px", fontSize: 12, fontWeight: checked ? 600 : 400,
                  cursor: "pointer", background: "none", border: "none",
                  color: checked ? "var(--accent)" : "var(--text-primary)",
                }}
                onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--bg-card-hover)"}
                onMouseLeave={e => e.currentTarget.style.backgroundColor = ""}
              >
                <div style={{
                  width: 14, height: 14, borderRadius: 3, flexShrink: 0,
                  border: `2px solid ${checked ? "var(--accent)" : "var(--border-primary)"}`,
                  backgroundColor: checked ? "var(--accent)" : "transparent",
                  display: "flex", alignItems: "center", justifyContent: "center",
                }}>
                  {checked && <span style={{ color: "#fff", fontSize: 9, lineHeight: 1 }}>✓</span>}
                </div>
                {opt.label}
              </button>
            );
          })}
          {count > 0 && (
            <button
              onClick={() => { onChange(new Set()); setOpen(false); }}
              style={{
                display: "block", width: "100%", textAlign: "center", padding: "7px 14px",
                fontSize: 11, cursor: "pointer", background: "none", border: "none",
                borderTop: "1px solid var(--border-secondary)", color: "var(--text-muted)",
              }}
              onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--bg-card-hover)"}
              onMouseLeave={e => e.currentTarget.style.backgroundColor = ""}
            >
              Clear filters
            </button>
          )}
        </div>
      )}
    </div>
  );
}

// ── Sort dropdown ────────────────────────────────────────────────────────────

function SortDropdown({ value, onChange }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const current = SORT_OPTIONS.find(o => o.value === value) || SORT_OPTIONS[0];

  return (
    <div style={{ position: "relative" }} ref={ref}>
      <button
        onClick={() => setOpen(v => !v)}
        className="flex items-center gap-1.5 px-3 py-2 text-sm rounded-md border hover:opacity-80 cursor-pointer transition-opacity"
        style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-primary)", color: "var(--text-secondary)", whiteSpace: "nowrap" }}
      >
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4h13M3 8h9m-9 4h6m4 0l4-4m0 0l4 4m-4-4v12" />
        </svg>
        {current.label}
      </button>
      {open && (
        <div style={{
          position: "absolute", right: 0, top: "calc(100% + 4px)", zIndex: 20,
          backgroundColor: "var(--bg-card)", border: "1px solid var(--border-primary)",
          borderRadius: 8, minWidth: 180, boxShadow: "0 8px 24px rgba(0,0,0,0.15)", overflow: "hidden",
        }}>
          {SORT_OPTIONS.map(opt => (
            <button
              key={opt.value}
              onClick={() => { onChange(opt.value); setOpen(false); }}
              style={{
                display: "block", width: "100%", textAlign: "left",
                padding: "9px 14px", fontSize: 12, fontWeight: opt.value === value ? 600 : 400,
                cursor: "pointer", background: "none", border: "none",
                color: opt.value === value ? "var(--accent)" : "var(--text-primary)",
              }}
              onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--bg-card-hover)"}
              onMouseLeave={e => e.currentTarget.style.backgroundColor = ""}
            >
              {opt.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ── Notes mode toggle ────────────────────────────────────────────────────────

function NotesModeToggle({ value, onChange }) {
  const isExpanded = value === "expanded";
  return (
    <button
      onClick={() => onChange(isExpanded ? "quick" : "expanded")}
      className="flex items-center gap-1.5 px-3 py-2 text-sm rounded-md border hover:opacity-80 cursor-pointer transition-opacity"
      title={isExpanded ? "Switch to Quick notes view" : "Switch to Expanded notes view"}
      style={{
        backgroundColor: isExpanded ? "color-mix(in srgb, var(--accent) 15%, var(--bg-input))" : "var(--bg-input)",
        borderColor: isExpanded ? "var(--accent)" : "var(--border-primary)",
        color: isExpanded ? "var(--accent)" : "var(--text-secondary)",
        whiteSpace: "nowrap",
      }}
    >
      {isExpanded ? (
        // Expanded icon: lines with detail
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 10h16M4 14h10M4 18h7" />
        </svg>
      ) : (
        // Quick icon: compact list
        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
        </svg>
      )}
      Notes: {isExpanded ? "Expanded" : "Quick"}
    </button>
  );
}

// ── Helpers ──────────────────────────────────────────────────────────────────

function primaryContact(customer, type) {
  const contacts = customer.contacts || [];
  const primary = contacts.find((c) => c.type === type && c.primary);
  return primary?.value || contacts.find((c) => c.type === type)?.value || null;
}

function ActionsDropdown({ customer, onUpdate }) {
  const [open, setOpen] = useState(false);
  const [menuPos, setMenuPos] = useState({ top: 0, right: 0 });
  const [loading, setLoading] = useState(null);
  const btnRef = useRef(null);
  const menuRef = useRef(null);

  useEffect(() => {
    const handler = (e) => {
      if (
        btnRef.current && !btnRef.current.contains(e.target) &&
        menuRef.current && !menuRef.current.contains(e.target)
      ) setOpen(false);
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, []);

  const handleOpen = (e) => {
    e.stopPropagation();
    if (open) { setOpen(false); return; }
    const rect = btnRef.current.getBoundingClientRect();
    setMenuPos({ top: rect.bottom + 4, right: window.innerWidth - rect.right });
    setOpen(true);
  };

  const toggle = async (type, e) => {
    e.stopPropagation();
    setLoading(type);
    try {
      const endpoint = type === "negotiating"
        ? `/crm/customers/${customer.id}/toggle-negotiating`
        : `/crm/customers/${customer.id}/toggle-problem`;
      const updated = await api.post(endpoint);
      onUpdate(updated);
    } catch {
      alert("Failed to update status");
    } finally {
      setLoading(null);
      setOpen(false);
    }
  };

  return (
    <div onClick={e => e.stopPropagation()}>
      <button
        ref={btnRef}
        onClick={handleOpen}
        style={{
          padding: "4px 10px", fontSize: 11, fontWeight: 600, borderRadius: 5,
          border: "1px solid var(--border-primary)", cursor: "pointer",
          backgroundColor: "transparent", color: "var(--text-secondary)",
        }}
      >
        Actions ▾
      </button>
      {open && (
        <div
          ref={menuRef}
          onClick={e => e.stopPropagation()}
          style={{
            position: "fixed", top: menuPos.top, right: menuPos.right, zIndex: 9999,
            backgroundColor: "var(--bg-card)", border: "1px solid var(--border-primary)",
            borderRadius: 8, minWidth: 180, boxShadow: "0 8px 24px rgba(0,0,0,0.18)",
            overflow: "hidden",
          }}
        >
          <button
            onClick={(e) => toggle("negotiating", e)}
            disabled={loading === "negotiating"}
            style={{
              display: "block", width: "100%", textAlign: "left",
              padding: "9px 14px", fontSize: 12, fontWeight: 500, cursor: "pointer",
              background: "none", border: "none",
              color: customer.negotiating ? "#a16207" : "var(--text-primary)",
              borderBottom: "1px solid var(--border-secondary)",
            }}
            onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--bg-card-hover)"}
            onMouseLeave={e => e.currentTarget.style.backgroundColor = ""}
          >
            {loading === "negotiating" ? "..." : customer.negotiating ? "End Negotiations" : "Start Negotiating"}
          </button>
          <button
            onClick={(e) => toggle("problem", e)}
            disabled={loading === "problem"}
            style={{
              display: "block", width: "100%", textAlign: "left",
              padding: "9px 14px", fontSize: 12, fontWeight: 500, cursor: "pointer",
              background: "none", border: "none",
              color: customer.has_problem ? "#b91c1c" : "var(--text-primary)",
            }}
            onMouseEnter={e => e.currentTarget.style.backgroundColor = "var(--bg-card-hover)"}
            onMouseLeave={e => e.currentTarget.style.backgroundColor = ""}
          >
            {loading === "problem" ? "..." : customer.has_problem ? "Resolve Issue" : "Has Problem"}
          </button>
        </div>
      )}
    </div>
  );
}

// ── Main component ───────────────────────────────────────────────────────────

export default function CustomerList() {
  const [customers, setCustomers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [search, setSearch] = useState("");
  const [sort, setSort] = useState("default");
  const [activeFilters, setActiveFilters] = useState(new Set());
  const [hoveredRow, setHoveredRow] = useState(null);
  const [colPrefs, setColPrefs] = useState(loadColumnPrefs);
  // Map of customer_id → "inbound" | "outbound" | null
  const [commDirections, setCommDirections] = useState({});
  // Map of customer_id → ISO date string of last comm
  const [lastCommDates, setLastCommDates] = useState({});
  const [notesMode, setNotesMode] = useState(
    () => localStorage.getItem(NOTES_MODE_KEY) || "quick"
  );
  const [pageSize, setPageSize] = useState(20);
  const [page, setPage] = useState(1);
  const navigate = useNavigate();
  const { hasPermission } = useAuth();
  const canEdit = hasPermission("crm", "edit");

  const handleNotesModeChange = (mode) => {
    setNotesMode(mode);
    localStorage.setItem(NOTES_MODE_KEY, mode);
  };

  const fetchCustomers = async () => {
    setLoading(true);
    setError("");
    try {
      const params = new URLSearchParams();
      if (search) params.set("search", search);
      if (sort)   params.set("sort", sort);
      const qs = params.toString();
      const data = await api.get(`/crm/customers${qs ? `?${qs}` : ""}`);
      setCustomers(data.customers);
      // Fetch last-comm directions only for customers with a status flag
      fetchDirections(data.customers);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  const fetchDirections = async (list) => {
    const flagged = list.filter(c => c.negotiating || c.has_problem);
    if (!flagged.length) return;
    const results = await Promise.allSettled(
      flagged.map(c =>
        api.get(`/crm/customers/${c.id}/last-comm-direction`)
          .then(r => [c.id, r.direction, r.occurred_at || r.date || null])
          .catch(() => [c.id, null, null])
      )
    );
    const dirMap = {};
    const dateMap = {};
    for (const r of results) {
      if (r.status === "fulfilled") {
        const [id, dir, date] = r.value;
        dirMap[id] = dir;
        if (date) dateMap[id] = date;
      }
    }
    setCommDirections(prev => ({ ...prev, ...dirMap }));
    setLastCommDates(prev => ({ ...prev, ...dateMap }));
  };

  useEffect(() => { fetchCustomers(); }, [search, sort]);

  const updateColVisible = (id, vis) => {
    const col = ALL_COLUMNS.find(c => c.id === id);
    if (col?.locked) return; // can't toggle locked columns
    const next = { ...colPrefs.visible, [id]: vis };
    setColPrefs((p) => ({ ...p, visible: next }));
    saveColumnPrefs(next, colPrefs.orderedIds);
  };

  const updateColOrder = (orderedIds) => {
    setColPrefs((p) => ({ ...p, orderedIds }));
    saveColumnPrefs(colPrefs.visible, orderedIds);
  };

  const visibleCols = colPrefs.orderedIds
    .map((id) => ALL_COLUMNS.find((c) => c.id === id))
    .filter((c) => c && colPrefs.visible[c.id]);

  const filteredCustomers = activeFilters.size === 0 ? customers : customers.filter(c =>
    (!activeFilters.has("negotiating") || c.negotiating) &&
    (!activeFilters.has("has_problem") || c.has_problem)
  );

  const totalPages = pageSize > 0 ? Math.ceil(filteredCustomers.length / pageSize) : 1;
  const safePage = Math.min(page, Math.max(1, totalPages));
  const pagedCustomers = pageSize > 0
    ? filteredCustomers.slice((safePage - 1) * pageSize, safePage * pageSize)
    : filteredCustomers;

  const handleCustomerUpdate = (updated) => {
    setCustomers(prev => prev.map(c => c.id === updated.id ? updated : c));
    // Refresh direction for this customer if it now has/lost a flag
    if (updated.negotiating || updated.has_problem) {
      api.get(`/crm/customers/${updated.id}/last-comm-direction`)
        .then(r => {
          setCommDirections(prev => ({ ...prev, [updated.id]: r.direction }));
          if (r.occurred_at || r.date) setLastCommDates(prev => ({ ...prev, [updated.id]: r.occurred_at || r.date }));
        })
        .catch(() => {});
    }
  };

  const renderCell = (col, c, direction) => {
    const loc = c.location || {};
    switch (col.id) {
      case "name":
        return (
          <td key={col.id} className="px-4 py-3 font-medium" style={{ color: "var(--text-heading)" }}>
            <span>{[TITLE_SHORT[c.title], c.name, c.surname].filter(Boolean).join(" ")}</span>
          </td>
        );
      case "status":
        return <StatusIconsCell key={col.id} customer={c} direction={direction} />;
      case "organization":
        return <td key={col.id} className="px-4 py-3" style={{ color: "var(--text-primary)" }}>{c.organization || "—"}</td>;
      case "address": {
        const parts = [loc.address, loc.postal_code, loc.city, loc.region, loc.country].filter(Boolean);
        return <td key={col.id} className="px-4 py-3 text-xs" style={{ color: "var(--text-muted)" }}>{parts.join(", ") || "—"}</td>;
      }
      case "location": {
        const cityCountry = [loc.city, loc.country].filter(Boolean).join(", ");
        return <td key={col.id} className="px-4 py-3 text-xs" style={{ color: "var(--text-muted)", whiteSpace: "nowrap" }}>{cityCountry || "—"}</td>;
      }
      case "email":
        return <td key={col.id} className="px-4 py-3 text-xs" style={{ color: "var(--text-muted)" }}>{primaryContact(c, "email") || "—"}</td>;
      case "phone":
        return <td key={col.id} className="px-4 py-3 text-xs" style={{ color: "var(--text-muted)", whiteSpace: "nowrap" }}>{primaryContact(c, "phone") || "—"}</td>;
      case "religion":
        return <td key={col.id} className="px-4 py-3 text-xs" style={{ color: "var(--text-muted)" }}>{c.religion || "—"}</td>;
      case "language":
        return <td key={col.id} className="px-4 py-3 text-xs" style={{ color: "var(--text-muted)" }}>{resolveLanguage(c.language)}</td>;
      case "tags":
        return (
          <td key={col.id} className="px-4 py-3">
            <div className="flex flex-wrap gap-1">
              {(c.tags || []).slice(0, 3).map((tag) => (
                <span key={tag} className="px-2 py-0.5 text-xs rounded-full"
                  style={{ backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)" }}>
                  {tag}
                </span>
              ))}
              {(c.tags || []).length > 3 && (
                <span className="text-xs" style={{ color: "var(--text-muted)" }}>+{c.tags.length - 3}</span>
              )}
            </div>
          </td>
        );
      default:
        return <td key={col.id} className="px-4 py-3" style={{ color: "var(--text-muted)" }}>—</td>;
    }
  };

  // In expanded mode, hide the status column — info is shown as sub-rows instead
  const visibleColsForMode = notesMode === "expanded"
    ? visibleCols.filter(c => c.id !== "status")
    : visibleCols;

  // Total column count for colSpan on expanded sub-rows
  const totalCols = visibleColsForMode.length + (canEdit ? 1 : 0);

  // Row gradient background for customers with active status flags
  function rowGradient(customer, direction) {
    const hasNeg = customer.negotiating;
    const hasIssue = customer.has_problem;
    if (!hasNeg && !hasIssue) return undefined;
    const pendingOurReply = direction === "inbound";
    const color = hasIssue
      ? (pendingOurReply ? "rgba(224, 53, 53, 0.07)" : "rgba(224, 53, 53, 0.05)")
      : (pendingOurReply ? "rgba(247, 103, 7, 0.07)" : "rgba(232, 165, 4, 0.05)");
    return `linear-gradient(to right, ${color} 0%, transparent 70%)`;
  }

  return (
    <div>
      <div className="flex items-center justify-between mb-6">
        <h1 className="text-2xl font-bold" style={{ color: "var(--text-heading)" }}>Customers</h1>
        {canEdit && (
          <button
            onClick={() => navigate("/crm/customers/new")}
            className="px-4 py-2 text-sm rounded-md hover:opacity-90 transition-colors cursor-pointer"
            style={{ backgroundColor: "var(--btn-primary)", color: "var(--text-white)" }}
          >
            New Customer
          </button>
        )}
      </div>

      <div className="flex gap-3 mb-4">
        <input
          type="text"
          placeholder="Search by name, organization, address, email, phone, religion, language, tags..."
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="flex-1 px-3 py-2 text-sm rounded-md border"
          style={inputStyle}
        />
        <SortDropdown value={sort} onChange={setSort} />
        <NotesModeToggle value={notesMode} onChange={handleNotesModeChange} />
        <FilterDropdown active={activeFilters} onChange={setActiveFilters} />
        <select
          value={String(pageSize)}
          onChange={(e) => { setPageSize(Number(e.target.value)); setPage(1); }}
          className="px-3 py-2 text-sm rounded-md border cursor-pointer"
          style={{ backgroundColor: "var(--bg-input)", borderColor: "var(--border-primary)", color: "var(--text-primary)" }}
        >
          <option value="10">10 / page</option>
          <option value="20">20 / page</option>
          <option value="50">50 / page</option>
          <option value="0">All</option>
        </select>
        <ColumnToggle
          visible={colPrefs.visible}
          orderedIds={colPrefs.orderedIds}
          onChange={updateColVisible}
          onReorder={updateColOrder}
        />
      </div>

      {error && (
        <div className="text-sm rounded-md p-3 mb-4 border"
          style={{ backgroundColor: "var(--danger-bg)", borderColor: "var(--danger)", color: "var(--danger-text)" }}>
          {error}
        </div>
      )}

      {loading ? (
        <div className="text-center py-8" style={{ color: "var(--text-muted)" }}>Loading...</div>
      ) : filteredCustomers.length === 0 ? (
        <div className="rounded-lg p-8 text-center text-sm border"
          style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)", color: "var(--text-muted)" }}>
          {activeFilters.size > 0 ? "No customers match the current filters." : "No customers found."}
        </div>
      ) : (
        <div className="rounded-lg overflow-hidden border"
          style={{ backgroundColor: "var(--bg-card)", borderColor: "var(--border-primary)" }}>
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr style={{ backgroundColor: "var(--bg-primary)", borderBottom: "1px solid var(--border-primary)" }}>
                  {visibleColsForMode.map((col) => (
                    <th key={col.id} className="px-4 py-3 font-medium" style={{ color: "var(--text-secondary)", textAlign: col.id === "status" ? "center" : "left", ...(col.id === "status" ? { width: 90 } : {}) }}>
                      {col.label}
                    </th>
                  ))}
                  {canEdit && <th className="px-4 py-3 text-right font-medium" style={{ color: "var(--text-secondary)" }}></th>}
                </tr>
              </thead>
              <tbody>
                {pagedCustomers.map((c, index) => {
                  const direction = commDirections[c.id] ?? null;
                  const lastDate = lastCommDates[c.id] ?? null;
                  const hasStatus = c.negotiating || c.has_problem;
                  const isLast = index === pagedCustomers.length - 1;
                  const gradient = rowGradient(c, direction);
                  const rowBg = hoveredRow === c.id ? "var(--bg-card-hover)" : undefined;
                  const zebraBase = index % 2 === 1 ? "var(--bg-row-alt)" : "transparent";
                  const rowBackground = gradient
                    ? `${gradient}, ${zebraBase}`
                    : zebraBase;
                  const rowStyle = {
                    borderBottom: (!isLast && !(notesMode === "expanded" && hasStatus))
                      ? "1px solid var(--border-secondary)"
                      : "none",
                    background: rowBg ? rowBg : rowBackground,
                  };

                  const mainRow = (
                    <tr
                      key={`${c.id}-main`}
                      onClick={() => navigate(`/crm/customers/${c.id}`)}
                      className="cursor-pointer"
                      style={rowStyle}
                      onMouseEnter={() => setHoveredRow(c.id)}
                      onMouseLeave={() => setHoveredRow(null)}
                    >
                      {visibleColsForMode.map((col) => renderCell(col, c, direction))}
                      {canEdit && (
                        <td className="px-4 py-3 text-right">
                          <ActionsDropdown customer={c} onUpdate={handleCustomerUpdate} />
                        </td>
                      )}
                    </tr>
                  );

                  if (notesMode === "expanded" && hasStatus) {
                    const { negColor, issColor, pendingOurReply } = statusColors(direction);
                    const when = relDays(lastDate);
                    const subRowBg = hoveredRow === c.id ? "var(--bg-card-hover)" : undefined;

                    const subRows = [];

                    if (c.negotiating) {
                      let text;
                      if (pendingOurReply) {
                        text = when
                          ? `Undergoing negotiations — client last contacted us ${when}. Reply needed.`
                          : "Undergoing negotiations — client is awaiting our reply.";
                      } else {
                        text = when
                          ? `Undergoing negotiations — we last reached out ${when}.`
                          : "Undergoing negotiations.";
                      }
                      subRows.push(
                        <tr
                          key={`${c.id}-neg`}
                          className="cursor-pointer"
                          onClick={() => navigate(`/crm/customers/${c.id}`)}
                          style={{
                            borderBottom: "none",
                            background: subRowBg ? subRowBg : rowBackground,
                          }}
                          onMouseEnter={() => setHoveredRow(c.id)}
                          onMouseLeave={() => setHoveredRow(null)}
                        >
                          <td colSpan={totalCols} style={{ padding: "0px 16px 5px 16px" }}>
                            <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
                              <span style={{ color: negColor, display: "inline-flex" }}>
                                <IconNegotiations style={{ width: EXP_NEG_ICON_SIZE, height: EXP_NEG_ICON_SIZE, flexShrink: 0 }} />
                              </span>
                              {pendingOurReply && (
                                <span style={{ color: "var(--crm-status-alert)", display: "inline-flex" }}>
                                  <IconImportant style={{ width: EXP_IMP_ICON_SIZE, height: EXP_IMP_ICON_SIZE, flexShrink: 0 }} className="crm-icon-breathe" />
                                </span>
                              )}
                              <span style={{ fontSize: 11.5, color: negColor, fontWeight: 500 }}>{text}</span>
                            </div>
                          </td>
                        </tr>
                      );
                    }

                    if (c.has_problem) {
                      let text;
                      if (pendingOurReply) {
                        text = when
                          ? `Open issue — client reached out ${when} and is awaiting our response.`
                          : "Open issue — client is awaiting our response.";
                      } else {
                        text = when
                          ? `Open issue — we last contacted the client ${when}.`
                          : "Open issue — under investigation.";
                      }
                      subRows.push(
                        <tr
                          key={`${c.id}-iss`}
                          className="cursor-pointer"
                          onClick={() => navigate(`/crm/customers/${c.id}`)}
                          style={{
                            borderBottom: "none",
                            background: subRowBg ? subRowBg : rowBackground,
                          }}
                          onMouseEnter={() => setHoveredRow(c.id)}
                          onMouseLeave={() => setHoveredRow(null)}
                        >
                          <td colSpan={totalCols} style={{ padding: "0px 16px 5px 16px" }}>
                            <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
                              <span style={{ color: issColor, display: "inline-flex" }}>
                                <IconIssues style={{ width: EXP_ISS_ICON_SIZE, height: EXP_ISS_ICON_SIZE, flexShrink: 0 }} />
                              </span>
                              {pendingOurReply && (
                                <span style={{ color: "var(--crm-status-danger)", display: "inline-flex" }}>
                                  <IconImportant style={{ width: EXP_IMP_ICON_SIZE, height: EXP_IMP_ICON_SIZE, flexShrink: 0 }} className="crm-icon-breathe" />
                                </span>
                              )}
                              <span style={{ fontSize: 11.5, color: issColor, fontWeight: 500 }}>{text}</span>
                            </div>
                          </td>
                        </tr>
                      );
                    }

                    if (!isLast) {
                      subRows.push(
                        <tr key={`${c.id}-gap`} style={{ borderBottom: "1px solid var(--border-secondary)" }}>
                          <td colSpan={totalCols} style={{ padding: 0 }} />
                        </tr>
                      );
                    }

                    return [mainRow, ...subRows].filter(Boolean);
                  }

                  return (
                    <tr
                      key={c.id}
                      onClick={() => navigate(`/crm/customers/${c.id}`)}
                      className="cursor-pointer"
                      style={{
                        borderBottom: !isLast ? "1px solid var(--border-secondary)" : "none",
                        background: rowBg
                          ? rowBg
                          : gradient || "transparent",
                      }}
                      onMouseEnter={() => setHoveredRow(c.id)}
                      onMouseLeave={() => setHoveredRow(null)}
                    >
                      {visibleColsForMode.map((col) => renderCell(col, c, direction))}
                      {canEdit && (
                        <td className="px-4 py-3 text-right">
                          <ActionsDropdown customer={c} onUpdate={handleCustomerUpdate} />
                        </td>
                      )}
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          {pageSize > 0 && totalPages > 1 && (
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "10px 16px", borderTop: "1px solid var(--border-primary)" }}>
              <span style={{ fontSize: 12, color: "var(--text-muted)" }}>
                Page {safePage} of {totalPages} — {filteredCustomers.length} total
              </span>
              <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
                {[
                  { label: "«", onClick: () => setPage(1), disabled: safePage === 1 },
                  { label: "‹", onClick: () => setPage((p) => Math.max(1, p - 1)), disabled: safePage === 1 },
                ].map(({ label, onClick, disabled }) => (
                  <button key={label} onClick={onClick} disabled={disabled}
                    style={{ padding: "3px 8px", fontSize: 12, borderRadius: 4, cursor: disabled ? "default" : "pointer", opacity: disabled ? 0.4 : 1, backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)", border: "none" }}>
                    {label}
                  </button>
                ))}
                {Array.from({ length: totalPages }, (_, i) => i + 1)
                  .filter((p) => p === 1 || p === totalPages || Math.abs(p - safePage) <= 2)
                  .reduce((acc, p, idx, arr) => {
                    if (idx > 0 && p - arr[idx - 1] > 1) acc.push("…");
                    acc.push(p);
                    return acc;
                  }, [])
                  .map((p, idx) =>
                    p === "…" ? (
                      <span key={`e-${idx}`} style={{ padding: "0 4px", fontSize: 12, color: "var(--text-muted)" }}>…</span>
                    ) : (
                      <button key={p} onClick={() => setPage(p)}
                        style={{ padding: "3px 8px", fontSize: 12, borderRadius: 4, cursor: "pointer", fontWeight: p === safePage ? 700 : 400, backgroundColor: p === safePage ? "var(--accent)" : "var(--bg-card-hover)", color: p === safePage ? "var(--bg-primary)" : "var(--text-secondary)", border: "none" }}>
                        {p}
                      </button>
                    )
                  )}
                {[
                  { label: "›", onClick: () => setPage((p) => Math.min(totalPages, p + 1)), disabled: safePage === totalPages },
                  { label: "»", onClick: () => setPage(totalPages), disabled: safePage === totalPages },
                ].map(({ label, onClick, disabled }) => (
                  <button key={label} onClick={onClick} disabled={disabled}
                    style={{ padding: "3px 8px", fontSize: 12, borderRadius: 4, cursor: disabled ? "default" : "pointer", opacity: disabled ? 0.4 : 1, backgroundColor: "var(--bg-card-hover)", color: "var(--text-secondary)", border: "none" }}>
                    {label}
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
