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

// ── Customer-status SVG icon imports ─────────────────────────────────────────
import clientIcon            from "../../assets/customer-status/client.svg?raw";
import negotiatingIcon       from "../../assets/customer-status/negotiating.svg?raw";
import awaitingQuotationIcon from "../../assets/customer-status/awating-quotation.svg?raw";
import awaitingConfirmIcon   from "../../assets/customer-status/awaiting-confirmation.svg?raw";
import quotationAcceptedIcon from "../../assets/customer-status/quotation-accepted.svg?raw";
import startedMfgIcon        from "../../assets/customer-status/started-mfg.svg?raw";
import awaitingPaymentIcon   from "../../assets/customer-status/awaiting-payment.svg?raw";
import shippedIcon           from "../../assets/customer-status/shipped.svg?raw";
import inactiveIcon          from "../../assets/customer-status/inactive.svg?raw";
import declinedIcon          from "../../assets/customer-status/declined.svg?raw";
import churnedIcon           from "../../assets/customer-status/churned.svg?raw";

import orderIcon             from "../../assets/customer-status/order.svg?raw";
import exclamationIcon       from "../../assets/customer-status/exclamation.svg?raw";
import wrenchIcon            from "../../assets/customer-status/wrench.svg?raw";

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: "support",      label: "Support",       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));
}


// ── 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 };
}

// ── Customer status icon resolver ─────────────────────────────────────────────
// Pre-manufacturing statuses: customer can still go silent/churn
const PRE_MFG_STATUSES = new Set([
  "negotiating", "awaiting_quotation", "awaiting_customer_confirmation",
  "awaiting_fulfilment", "awaiting_payment",
]);

// Returns { icon, color, title } for a customer based on their status + orders
function resolveStatusIcon(customer) {
  const status = customer.relationship_status || "lead";
  const summary = customer.crm_summary || {};
  const allOrders = summary.all_orders_statuses || [];

  // ── Churned ────────────────────────────────────────────────────────────────
  if (status === "churned") {
    return { icon: churnedIcon, color: "var(--crm-customer-icon-muted)", title: "Churned" };
  }

  // ── Lead / Prospect ────────────────────────────────────────────────────────
  if (status === "lead") {
    return { icon: clientIcon, color: "var(--crm-customer-icon-lead)", title: "Lead" };
  }
  if (status === "prospect") {
    return { icon: clientIcon, color: "var(--crm-customer-icon-info)", title: "Prospect" };
  }

  // ── Inactive ───────────────────────────────────────────────────────────────
  // Always show inactive icon; backend polling corrects wrongly-inactive records.
  if (status === "inactive") {
    return { icon: inactiveIcon, color: "var(--crm-customer-icon-muted)", title: "Inactive" };
  }

  // ── Active ─────────────────────────────────────────────────────────────────
  if (status === "active") {
    const activeOrderStatus = summary.active_order_status;

    const orderIconMap = {
      negotiating:                    { icon: negotiatingIcon,       color: "var(--crm-customer-icon-passive)",  title: "Negotiating" },
      awaiting_quotation:             { icon: awaitingQuotationIcon, color: "var(--crm-customer-icon-passive)",  title: "Awaiting Quotation" },
      awaiting_customer_confirmation: { icon: awaitingConfirmIcon,   color: "var(--crm-customer-icon-passive)",  title: "Awaiting Confirmation" },
      awaiting_fulfilment:            { icon: quotationAcceptedIcon, color: "var(--crm-customer-icon-info)",     title: "Awaiting Fulfilment" },
      awaiting_payment:               { icon: awaitingPaymentIcon,   color: "var(--crm-customer-icon-payment)",  title: "Awaiting Payment" },
      manufacturing:                  { icon: startedMfgIcon,        color: "var(--crm-customer-icon-positive)", title: "Manufacturing" },
      shipped:                        { icon: shippedIcon,           color: "var(--crm-customer-icon-positive)", title: "Shipped" },
      installed:                      { icon: inactiveIcon,          color: "var(--crm-customer-icon-positive)", title: "Installed" },
    };

    // 1. There is an open order → show its icon.
    //    active_order_status is only set for non-terminal (non-declined, non-complete) orders.
    if (activeOrderStatus && orderIconMap[activeOrderStatus]) {
      return orderIconMap[activeOrderStatus];
    }

    // From here: no open orders. Determine why via all_orders_statuses.
    // Note: all_orders_statuses may be absent on older records not yet re-summarised.
    const allDeclined = allOrders.length > 0 && allOrders.every((s) => s === "declined");
    const allComplete = allOrders.length > 0 && allOrders.every((s) => s === "complete");

    // 2. All orders declined → show declined icon; staff decides next step.
    if (allDeclined) {
      return { icon: declinedIcon, color: "var(--crm-customer-icon-declined)", title: "All orders declined" };
    }

    // 3. All orders complete → should have auto-flipped to inactive already.
    if (allComplete) {
      return { icon: inactiveIcon, color: "var(--crm-customer-icon-positive)", title: "All orders complete" };
    }

    // 4. No orders at all (edge case: newly active, or old record without summary).
    return { icon: inactiveIcon, color: "var(--crm-customer-icon-info)", title: "Active, no orders" };
  }

  return { icon: clientIcon, color: "var(--crm-customer-icon-muted)", title: status };
}

// ── Status icon size ─────────────────────────────────────────────────────────

// Status icon box size (px) — same for all status icons so layout is consistent
const STATUS_ICON_SIZE = 22;

const REL_STATUS_STYLES = {
  lead:     { bg: "var(--crm-rel-lead-bg)",     color: "var(--crm-rel-lead-text)",     border: "var(--crm-rel-lead-border)" },
  prospect: { bg: "var(--crm-rel-prospect-bg)", color: "var(--crm-rel-prospect-text)", border: "var(--crm-rel-prospect-border)" },
  active:   { bg: "var(--crm-rel-active-bg)",   color: "var(--crm-rel-active-text)",   border: "var(--crm-rel-active-border)" },
  inactive: { bg: "var(--crm-rel-inactive-bg)", color: "var(--crm-rel-inactive-text)", border: "var(--crm-rel-inactive-border)" },
  churned:  { bg: "var(--crm-rel-churned-bg)",  color: "var(--crm-rel-churned-text)",  border: "var(--crm-rel-churned-border)" },
};
const REL_STATUS_LABELS = { lead:"Lead", prospect:"Prospect", active:"Active", inactive:"Inactive", churned:"Churned" };

const ORDER_STATUS_LABELS = {
  negotiating:"Negotiating", awaiting_quotation:"Awaiting Quotation",
  awaiting_customer_confirmation:"Awaiting Confirmation", awaiting_fulfilment:"Awaiting Fulfilment",
  awaiting_payment:"Awaiting Payment", manufacturing:"Manufacturing", shipped:"Shipped",
  installed:"Installed", declined:"Declined", complete:"Complete",
};

function renderMaskedIcon(icon, color, title, size = STATUS_ICON_SIZE) {
  const svgMarkup = icon
    .replace(/<\?xml[\s\S]*?\?>/gi, "")
    .replace(/<!DOCTYPE[\s\S]*?>/gi, "")
    .replace(/<!--[\s\S]*?-->/g, "")
    .replace(
      /<svg\b([^>]*)>/i,
      `<svg$1 width="${size}" height="${size}" aria-label="${title}" role="img" focusable="false" style="display:block;width:${size}px;height:${size}px;color:${color};fill:currentColor;">`,
    );

  return (
    <span
      title={title}
      aria-label={title}
      role="img"
      style={{
        width: size,
        height: size,
        display: "inline-flex",
        alignItems: "center",
        justifyContent: "center",
        verticalAlign: "middle",
        flexShrink: 0,
        lineHeight: 0,
      }}
      dangerouslySetInnerHTML={{ __html: svgMarkup }}
    />
  );
}

function StatusCell({ customer, lastCommDate, onChurnUpdate }) {
  const { icon, color, title } = resolveStatusIcon(customer);

  // Auto-churn: active + has an open pre-mfg order + 12+ months since last comm
  useEffect(() => {
    if ((customer.relationship_status || "lead") !== "active") return;
    if (!lastCommDate) return;
    const allOrders = (customer.crm_summary?.all_orders_statuses) || [];
    if (!allOrders.some((s) => PRE_MFG_STATUSES.has(s))) return;
    const days = Math.floor((Date.now() - new Date(lastCommDate).getTime()) / 86400000);
    if (days < 365) return;
    onChurnUpdate?.(customer.id);
  }, [customer.id, customer.relationship_status, lastCommDate]);

  return (
    <td className="px-3 py-3" style={{ textAlign: "center" }}>
      {renderMaskedIcon(icon, color, title)}
    </td>
  );
}

// ── Icon color filter system ──────────────────────────────────────────────────
// CSS filters starting from a black SVG source.
// ── Icon tinting ──────────────────────────────────────────────────────────────
// Maps every color token used in resolveStatusIcon to a pre-computed CSS filter.
// To change a color: update BOTH the color value in resolveStatusIcon AND add/update
// its entry here. Use https://codepen.io/sosuke/pen/Pjoqqp to generate the filter.
//
// All filters start with brightness(0) saturate(100%) to zero out the source black,
// then the remaining steps shift to the target color.
const ICON_FILTER_MAP = {
  // lead — near-white beige #f5f0e8
  "#f5f0e8":                      "brightness(0) saturate(100%) invert(96%) sepia(10%) saturate(200%) hue-rotate(330deg) brightness(103%)",
  // prospect / active / manufacturing / shipped / installed — green, var(--crm-rel-active-text) ≈ #22c55e
  "var(--crm-rel-active-text)":   "brightness(0) saturate(100%) invert(69%) sepia(48%) saturate(500%) hue-rotate(95deg) brightness(95%)",
  "var(--crm-rel-prospect-text)": "brightness(0) saturate(100%) invert(69%) sepia(48%) saturate(500%) hue-rotate(95deg) brightness(95%)",
  // inactive / churned / all-declined / silent — mid grey, var(--text-muted) ≈ #737373
  "var(--text-muted)":            "brightness(0) saturate(100%) invert(48%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(95%)",
  // negotiating / awaiting_quotation / awaiting_confirmation — bright grey, var(--text-primary) ≈ #d4d4d4
  "var(--text-primary)":          "brightness(0) saturate(100%) invert(87%) sepia(0%) saturate(0%) hue-rotate(0deg) brightness(100%)",
  // awaiting_fulfilment — light blue #7ab4e0
  "#7ab4e0":                      "brightness(0) saturate(100%) invert(67%) sepia(35%) saturate(500%) hue-rotate(182deg) brightness(105%)",
  // awaiting_payment — yellow #e8c040
  "#e8c040":                      "brightness(0) saturate(100%) invert(80%) sepia(55%) saturate(700%) hue-rotate(8deg) brightness(102%)",
  // declined — soft red #e07070
  "#e07070":                      "brightness(0) saturate(100%) invert(52%) sepia(40%) saturate(700%) hue-rotate(314deg) brightness(108%)",
};

function buildIconFilter(colorToken) {
  if (!colorToken) return "";
  return ICON_FILTER_MAP[colorToken] || "";
}

function SupportCell({ customer }) {
  const summary = customer.crm_summary || {};
  const hasIssue = (summary.active_issues_count || 0) > 0;
  const hasSupport = (summary.active_support_count || 0) > 0;
  if (!hasIssue && !hasSupport) return <td className="px-3 py-3" />;
  return (
    <td className="px-3 py-3">
      <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 4 }}>
        {hasIssue && (
          <span title={`${summary.active_issues_count} active technical issue(s)`}
            style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
            <span style={{ width: 10, height: 10, borderRadius: "50%", backgroundColor: "var(--crm-issue-active-text)", display: "inline-block", flexShrink: 0 }} />
            <span style={{ fontSize: 11, color: "var(--crm-issue-active-text)", fontWeight: 700 }}>{summary.active_issues_count}</span>
          </span>
        )}
        {hasSupport && (
          <span title={`${summary.active_support_count} active support item(s)`}
            style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
            <span style={{ width: 10, height: 10, borderRadius: "50%", backgroundColor: "var(--crm-support-active-text)", display: "inline-block", flexShrink: 0 }} />
            <span style={{ fontSize: 11, color: "var(--crm-support-active-text)", fontWeight: 700 }}>{summary.active_support_count}</span>
          </span>
        )}
      </div>
    </td>
  );
}

// ── 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: "lead",      label: "Lead" },
  { value: "prospect",  label: "Prospect" },
  { value: "active",    label: "Active" },
  { value: "inactive",  label: "Inactive" },
  { value: "churned",   label: "Churned" },
  { value: "has_issue", label: "Has Open Issue" },
  { value: "has_support", label: "Has Open Support" },
];

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 }) {
  const navigate = useNavigate();
  return (
    <button
      onClick={(e) => { e.stopPropagation(); navigate(`/crm/customers/${customer.id}`); }}
      style={{
        padding: "4px 10px", fontSize: 11, fontWeight: 600, borderRadius: 5,
        border: "1px solid var(--border-primary)", cursor: "pointer",
        backgroundColor: "transparent", color: "var(--text-secondary)",
      }}
    >
      Open
    </button>
  );
}

// ── 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) => {
    // Fetch last-comm for: active customers (for status icon + churn detection)
    // and customers with active issues/support (for sub-row context)
    const flagged = list.filter(c => {
      const s = c.crm_summary || {};
      const rel = c.relationship_status || "lead";
      return rel === "active" || (s.active_issues_count || 0) > 0 || (s.active_support_count || 0) > 0;
    });
    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 }));
  };

  const handleChurnUpdate = async (customerId) => {
    // Idempotent: only patch if still active
    setCustomers(prev => {
      const c = prev.find(x => x.id === customerId);
      if (!c || c.relationship_status !== "active") return prev;
      return prev.map(x => x.id === customerId ? { ...x, relationship_status: "churned" } : x);
    });
    try {
      await api.patch(`/crm/customers/${customerId}/relationship-status`, { status: "churned" });
    } catch {
      // silently ignore — local state already updated
    }
  };

  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 => {
    const summary = c.crm_summary || {};
    const relStatus = c.relationship_status || "lead";
    const relFilters = ["lead", "prospect", "active", "inactive", "churned"].filter(v => activeFilters.has(v));
    if (relFilters.length > 0 && !relFilters.includes(relStatus)) return false;
    if (activeFilters.has("has_issue") && !(summary.active_issues_count > 0)) return false;
    if (activeFilters.has("has_support") && !(summary.active_support_count > 0)) return false;
    return true;
  });

  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));
  };

  const renderCell = (col, c, direction, lastCommDate) => {
    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 <StatusCell key={col.id} customer={c} lastCommDate={lastCommDate} onChurnUpdate={handleChurnUpdate} />;
      case "support":
        return <SupportCell key={col.id} customer={c} />;
      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>;
    }
  };

  const visibleColsForMode = visibleCols;

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

  // Index of the "name" column among visible columns (sub-rows align under it)
  const nameColIndex = visibleColsForMode.findIndex(c => c.id === "name");

  // Row gradient background for customers with active issues or support items
  function rowGradient(customer) {
    const summary = customer.crm_summary || {};
    const hasIssue = (summary.active_issues_count || 0) > 0;
    const hasSupport = (summary.active_support_count || 0) > 0;
    if (!hasIssue && !hasSupport) return undefined;
    const color = hasIssue
      ? "rgba(224, 53, 53, 0.05)"
      : "rgba(247, 103, 7, 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" || col.id === "support") ? "center" : "left", ...(col.id === "status" ? { width: 90 } : {}), ...(col.id === "support" ? { width: 60 } : {}) }}>
                      {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 summary = c.crm_summary || {};
                  const hasStatus = (summary.active_issues_count || 0) > 0 || (summary.active_support_count || 0) > 0;
                  const isLast = index === pagedCustomers.length - 1;
                  const gradient = rowGradient(c);
                  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")
                      ? "1px solid var(--border-secondary)"
                      : "none",
                    background: rowBg ? rowBg : rowBackground,
                  };

                  // In expanded mode, hue overlay is applied on sub-rows (computed there)

                  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, lastDate))}
                      {canEdit && (
                        <td className="px-4 py-3 text-right">
                          <ActionsDropdown customer={c} onUpdate={handleCustomerUpdate} />
                        </td>
                      )}
                    </tr>
                  );

                  if (notesMode === "expanded") {
                    const subRowBg = hoveredRow === c.id ? "var(--bg-card-hover)" : undefined;
                    const issueCount = summary.active_issues_count || 0;
                    const supportCount = summary.active_support_count || 0;
                    const activeOrderStatus = summary.active_order_status;
                    const activeOrderNumber = summary.active_order_number;
                    const activeOrderTitle = summary.active_order_title;

                    // Sub-rows alternate tint relative to main row
                    const subRowLines = [];
                    if (activeOrderStatus) subRowLines.push("order");
                    if (issueCount > 0) subRowLines.push("issue");
                    if (supportCount > 0) subRowLines.push("support");

                    // Icon box size — fixed so text aligns regardless of icon
                    const SUB_ICON_BOX = 40;

                    // Hue tint for the whole customer block when issues/support exist
                    const hueGradient = issueCount > 0
                      ? "linear-gradient(to right, rgba(224, 53, 53, 0.07) 0%, transparent 70%)"
                      : supportCount > 0
                        ? "linear-gradient(to right, rgba(247, 103, 7, 0.07) 0%, transparent 70%)"
                        : null;

                    // All rows in this customer's block share the same zebra+hue tint
                    const sharedBg = subRowBg
                      ? subRowBg
                      : hueGradient
                        ? `${hueGradient}, ${zebraBase}`
                        : zebraBase;

                    // Columns before "name" get empty cells; content spans from name onward
                    const colsBeforeName = nameColIndex > 0 ? nameColIndex : 0;
                    const colsFromName = totalCols - colsBeforeName;

                    const makeSubRow = (key, content, isLastSubRow = false) => (
                      <tr
                        key={key}
                        className="cursor-pointer"
                        onClick={() => navigate(`/crm/customers/${c.id}`)}
                        style={{ borderBottom: "none", background: sharedBg }}
                        onMouseEnter={() => setHoveredRow(c.id)}
                        onMouseLeave={() => setHoveredRow(null)}
                      >
                        {colsBeforeName > 0 && (
                          <td colSpan={colsBeforeName} style={{ padding: 0 }} />
                        )}
                        <td colSpan={colsFromName} style={{ padding: isLastSubRow ? "4px 14px 14px 0" : "4px 16px 4px 0" }}>
                          {content}
                        </td>
                      </tr>
                    );

                    const { color: statusColor } = resolveStatusIcon(c);

                    const subRows = subRowLines.map((type, idx) => {
                      const isLastSubRow = idx === subRowLines.length - 1;
                      if (type === "issue") {
                        const label = `${issueCount} active technical issue${issueCount > 1 ? "s" : ""}`;
                        return makeSubRow(`${c.id}-iss`, (
                          <div style={{ display: "flex", alignItems: "center" }}>
                            <div style={{ width: SUB_ICON_BOX, flexShrink: 0, display: "flex", alignItems: "center", justifyContent: "center" }}>
                              {renderMaskedIcon(exclamationIcon, "var(--crm-customer-icon-declined)", "Issue", 15)}
                            </div>
                            <span style={{ fontSize: 11.5, color: "var(--crm-issue-active-text)", fontWeight: 500 }}>{label}</span>
                          </div>
                        ), isLastSubRow);
                      }
                      if (type === "support") {
                        const label = `${supportCount} active support ticket${supportCount > 1 ? "s" : ""}`;
                        return makeSubRow(`${c.id}-sup`, (
                          <div style={{ display: "flex", alignItems: "center" }}>
                            <div style={{ width: SUB_ICON_BOX, flexShrink: 0, display: "flex", alignItems: "center", justifyContent: "center" }}>
                              {renderMaskedIcon(wrenchIcon, "var(--crm-support-active-text)", "Support", 15)}
                            </div>
                            <span style={{ fontSize: 11.5, color: "var(--crm-support-active-text)", fontWeight: 500 }}>{label}</span>
                          </div>
                        ), isLastSubRow);
                      }
                      if (type === "order") {
                        const orderLabel = ORDER_STATUS_LABELS[activeOrderStatus] || activeOrderStatus;
                        const parts = ["Order", activeOrderNumber, orderLabel].filter(Boolean);
                        return makeSubRow(`${c.id}-ord`, (
                          <div style={{ display: "flex", alignItems: "center" }}>
                            <div style={{ width: SUB_ICON_BOX, flexShrink: 0, display: "flex", alignItems: "center", justifyContent: "center" }}>
                              {renderMaskedIcon(orderIcon, statusColor, orderLabel, 18)}
                            </div>
                            <span style={{ fontSize: 11.5, color: statusColor, fontWeight: 500 }}>
                              {parts.map((p, i) => (
                                <span key={i}>{i > 0 && <span style={{ margin: "0 5px", color: "var(--text-muted)" }}>·</span>}{p}</span>
                              ))}
                            </span>
                            {activeOrderTitle && (
                              <span style={{ fontSize: 11, color: "var(--text-muted)", marginLeft: 6 }}>· {activeOrderTitle}</span>
                            )}
                          </div>
                        ), isLastSubRow);
                      }
                      return null;
                    }).filter(Boolean);

                    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, lastDate))}
                      {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>
  );
}
