// Shared primitives — Digitalshop CRM
const { useState, useEffect, useRef, useCallback, useContext, createContext } = React;

// ── Language context ──────────────────────────────────────────────
const LangCtx = createContext("uk");

const LABELS = {
  uk: { orders: "Замовлення", calls: "Дзвінки", banking: "Банки", requests: "Заявки", settings: "Налаштування" },
  ru: { orders: "Заказы",     calls: "Звонки",  banking: "Банки", requests: "Заявки", settings: "Настройки"    },
};
function useLabels() {
  const lang = useContext(LangCtx);
  return LABELS[lang] || LABELS.uk;
}

// ── Status config ─────────────────────────────────────────────────
const STATUSES = {
  new:             { label: "Новий",               cls: "status-new",             horoshopId: 1  },
  waiting_reply:   { label: "Очікуємо відповідь",  cls: "status-waiting-reply",   horoshopId: 9  },
  processing:      { label: "В обробці",           cls: "status-processing",      horoshopId: 2  },
  shipped:         { label: "Надіслане",            cls: "status-shipped",         horoshopId: 6  },
  at_branch:       { label: "В відділенні",         cls: "status-at-branch",       horoshopId: 3  },
  completed:       { label: "Виконано",             cls: "status-completed",       horoshopId: 8  },
  cancelled:       { label: "Скасовано",            cls: "status-cancelled",       horoshopId: 4  },
  awaiting_supply: { label: "Очікує поставку",      cls: "status-awaiting-supply", horoshopId: 7  },
  preparing:       { label: "Готуємо до відправки", cls: "status-preparing",       horoshopId: 10 },
  client_thinking: { label: "Клієнт думає",         cls: "status-client-thinking", horoshopId: 11 },
  ttn_ready:       { label: "Готова ТТН",           cls: "status-ttn-ready",       horoshopId: 13 },
};

// Horoshop status_id → our key
const HOROSHOP_STATUS_MAP = {
  1: "new", 9: "waiting_reply", 2: "processing", 6: "shipped",
  3: "at_branch", 8: "completed", 4: "cancelled", 7: "awaiting_supply",
  10: "preparing", 11: "client_thinking", 13: "ttn_ready",
};

// ── Formatters ────────────────────────────────────────────────────
const MONTHS = ["січ.","лют.","бер.","квіт.","трав.","черв.","лип.","серп.","вер.","жовт.","лист.","груд."];
function fmtDate(str) {
  if (!str) return "—";
  const d = new Date(str.replace(" ", "T"));
  if (isNaN(d)) return str;
  const now = new Date();
  const isToday = d.toDateString() === now.toDateString();
  const hm = `${String(d.getHours()).padStart(2,"0")}:${String(d.getMinutes()).padStart(2,"0")}`;
  if (isToday) return `Сьогодні, ${hm}`;
  return `${d.getDate()} ${MONTHS[d.getMonth()]}, ${hm}`;
}
function fmtPhone(p) {
  if (!p) return "—";
  return p.replace(/(\+\d{2})(\d{3})(\d{3})(\d{2})(\d{2})/, "$1 $2 $3 $4 $5");
}
function copyText(text) {
  if (navigator.clipboard && window.isSecureContext) {
    navigator.clipboard.writeText(text);
  } else {
    const el = document.createElement("textarea");
    el.value = text;
    el.style.position = "fixed";
    el.style.opacity = "0";
    document.body.appendChild(el);
    el.select();
    document.execCommand("copy");
    document.body.removeChild(el);
  }
}
function fmtMoney(n) {
  if (n == null) return "—";
  return Number(n).toLocaleString("uk-UA").replace(/,/g, " ") + " ₴";
}
function fmtBalance(n) {
  return Number(n).toLocaleString("uk-UA", { minimumFractionDigits: 2, maximumFractionDigits: 2 }).replace(/,/g, " ") + " ₴";
}

// ── Icon (Lucide) ─────────────────────────────────────────────────
function Icon({ name, size = 20, color, style }) {
  const ref = useRef(null);
  useEffect(() => {
    if (ref.current && window.lucide) {
      ref.current.innerHTML = "";
      const el = document.createElement("i");
      el.setAttribute("data-lucide", name);
      el.style.width = size + "px";
      el.style.height = size + "px";
      if (color) el.style.color = color;
      ref.current.appendChild(el);
      window.lucide.createIcons({ nameAttr: "data-lucide" });
    }
  }, [name, size, color]);
  return <span ref={ref} style={{ display: "inline-flex", lineHeight: 0, flexShrink: 0, ...style }}/>;
}

// ── StatusChip ────────────────────────────────────────────────────
function StatusChip({ status }) {
  const s = STATUSES[status];
  if (!s) return <span className="status-chip status-new">—</span>;
  return <span className={`status-chip ${s.cls}`}>{s.label}</span>;
}

// ── Button ────────────────────────────────────────────────────────
function Button({ variant = "primary", size = "md", children, onClick, style, leftIcon, disabled }) {
  const base = {
    display: "inline-flex", alignItems: "center", gap: 8,
    border: 0, fontFamily: "inherit", fontWeight: 500, cursor: disabled ? "not-allowed" : "pointer",
    whiteSpace: "nowrap", transition: `all ${150}ms cubic-bezier(.2,0,0,1)`,
    opacity: disabled ? 0.5 : 1,
  };
  const sizes = {
    sm: { height: 28, padding: "0 10px", fontSize: 12, borderRadius: 6 },
    md: { height: 36, padding: "0 16px", fontSize: 13, borderRadius: 8 },
  };
  const variants = {
    primary:   { background: "var(--accent)", color: "#fff" },
    secondary: { background: "var(--bg-raised)", color: "var(--fg-primary)", border: "1px solid var(--border-default)" },
    ghost:     { background: "transparent", color: "var(--fg-secondary)" },
    danger:    { background: "rgba(244,63,94,.14)", color: "var(--danger)", border: "1px solid rgba(244,63,94,.3)" },
  };
  return (
    <button disabled={disabled} onClick={onClick} style={{ ...base, ...sizes[size], ...variants[variant], ...style }}>
      {leftIcon && <Icon name={leftIcon} size={size === "sm" ? 14 : 16}/>}
      {children}
    </button>
  );
}

// ── Avatar ────────────────────────────────────────────────────────
function Avatar({ name, size = 28 }) {
  const initials = (name || "?").split(" ").map(s => s[0]).slice(0, 2).join("");
  return (
    <div style={{
      width: size, height: size, borderRadius: "50%",
      background: "var(--bg-raised)", color: "var(--fg-primary)",
      display: "flex", alignItems: "center", justifyContent: "center",
      fontSize: size * 0.38, fontWeight: 600, border: "1px solid var(--border-default)", flexShrink: 0,
    }}>{initials}</div>
  );
}

// ── BankMonogram ──────────────────────────────────────────────────
function BankMonogram({ bank, size = 32 }) {
  const banks = {
    privat: { letter: "П", bg: "#5A9C32" },
    mono:   { letter: "M", bg: "#000000" },
    pumb:   { letter: "П", bg: "#E63946" },
    oschad: { letter: "О", bg: "#1E5F3B" },
  };
  const b = banks[bank] || banks.privat;
  return (
    <div style={{
      width: size, height: size, borderRadius: 6, background: b.bg, flexShrink: 0,
      display: "flex", alignItems: "center", justifyContent: "center",
      color: "#fff", fontWeight: 600, fontSize: size * 0.45,
    }}>{b.letter}</div>
  );
}

// ── Sidebar (desktop) ─────────────────────────────────────────────
function Sidebar({ active, onChange, userName = "Менеджер", role = "manager" }) {
  const L = useLabels();
  const [collapsed, setCollapsed] = useState(() => localStorage.getItem("crm_sidebar_collapsed") === "1");

  const toggle = () => setCollapsed(c => {
    localStorage.setItem("crm_sidebar_collapsed", c ? "0" : "1");
    return !c;
  });

  const items = [
    { key: "orders",   label: L.orders,   icon: "package"    },
    { key: "requests", label: L.requests, icon: "inbox"      },
    { key: "calls",    label: L.calls,    icon: "phone-call" },
    ...(role === "owner" ? [{ key: "banking", label: L.banking, icon: "wallet" }] : []),
    { key: "settings", label: L.settings, icon: "settings"   },
  ];

  const w = collapsed ? 56 : 240;

  return (
    <aside style={{
      width: w, height: "100dvh", background: "var(--bg-panel)",
      borderRight: "1px solid var(--border-subtle)",
      display: "flex", flexDirection: "column", flexShrink: 0,
      transition: "width 180ms var(--ease)", overflow: "hidden",
    }}>
      <div style={{ height: 56, display: "flex", alignItems: "center", justifyContent: collapsed ? "center" : "space-between", padding: collapsed ? "0 12px" : "0 8px 0 16px", borderBottom: "1px solid var(--border-subtle)", flexShrink: 0 }}>
        {!collapsed && (
          <svg width="148" height="28" viewBox="0 0 160 32" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ flexShrink: 0 }}>
            <rect x="0" y="4" width="24" height="24" rx="6" fill="#6366F1"/>
            <path d="M6 22 L18 10" stroke="white" strokeWidth="2.5" strokeLinecap="round"/>
            <circle cx="7.5" cy="20.5" r="1.75" fill="white"/>
            <circle cx="16.5" cy="11.5" r="1.75" fill="white"/>
            <text x="32" y="22" fontFamily="Inter, sans-serif" fontSize="16" fontWeight="600" fill="var(--fg-primary)" letterSpacing="-0.01em">Digitalshop</text>
          </svg>
        )}
        <button onClick={toggle} title={collapsed ? "Розгорнути" : "Згорнути"} style={{
          width: 30, height: 30, border: 0, borderRadius: 6, flexShrink: 0,
          background: "transparent", color: "var(--fg-muted)", cursor: "pointer",
          display: "flex", alignItems: "center", justifyContent: "center",
          transition: "color 150ms",
        }}>
          <Icon name={collapsed ? "panel-left-open" : "panel-left-close"} size={17}/>
        </button>
      </div>

      <nav style={{ padding: collapsed ? "8px 4px" : 8, display: "flex", flexDirection: "column", gap: 2, flex: 1 }}>
        {items.map(item => {
          const isActive = active === item.key;
          return (
            <button key={item.key} onClick={() => onChange(item.key)} title={collapsed ? item.label : undefined} style={{
              display: "flex", alignItems: "center", justifyContent: collapsed ? "center" : "flex-start", gap: 12,
              height: 36, padding: collapsed ? "0" : "0 12px", border: 0, borderRadius: 8, width: "100%",
              background: isActive ? "var(--accent-soft)" : "transparent",
              color: isActive ? "var(--accent)" : "var(--fg-secondary)",
              fontSize: 13, fontWeight: 500, cursor: "pointer", textAlign: "left", fontFamily: "inherit",
              transition: "all 150ms var(--ease)",
            }}>
              <Icon name={item.icon} size={18}/>
              {!collapsed && <span>{item.label}</span>}
            </button>
          );
        })}
      </nav>

      <div style={{ padding: collapsed ? "10px 4px" : 12, borderTop: "1px solid var(--border-subtle)", display: "flex", alignItems: "center", justifyContent: collapsed ? "center" : "flex-start", gap: 10, flexShrink: 0 }}>
        <Avatar name={userName} size={32}/>
        {!collapsed && (
          <div style={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
            <span style={{ fontSize: 12, fontWeight: 500, color: "var(--fg-primary)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{userName}</span>
            <span style={{ fontSize: 11, color: "var(--fg-muted)" }}>Digitalshop</span>
          </div>
        )}
      </div>
    </aside>
  );
}

// ── TopBar (desktop) ──────────────────────────────────────────────
function TopBar({ title }) {
  return (
    <div style={{
      height: 56, display: "flex", alignItems: "center", padding: "0 24px", gap: 16,
      borderBottom: "1px solid var(--border-subtle)", background: "var(--bg-panel)", flexShrink: 0,
    }}>
      <h1 style={{ fontSize: 16, fontWeight: 600, color: "var(--fg-primary)", margin: 0 }}>{title}</h1>
    </div>
  );
}

// ── BottomTabs (mobile) ───────────────────────────────────────────
function BottomTabs({ active, onChange, role = "manager" }) {
  const L = useLabels();
  const items = [
    { key: "orders",   label: L.orders,   icon: "package"    },
    { key: "requests", label: L.requests, icon: "inbox"      },
    { key: "calls",    label: L.calls,    icon: "phone-call" },
    ...(role === "owner" ? [{ key: "banking", label: L.banking, icon: "wallet" }] : []),
    { key: "settings", label: L.settings, icon: "settings"   },
  ];
  return (
    <div style={{
      position: "fixed", bottom: 0, left: 0, right: 0,
      background: "color-mix(in srgb, var(--bg-panel) 90%, transparent)",
      backdropFilter: "blur(20px)", WebkitBackdropFilter: "blur(20px)",
      borderTop: "1px solid var(--border-subtle)",
      display: "flex", flexDirection: "column", zIndex: 50,
    }}>
      <div style={{ display: "flex", height: "var(--tabbar-h)" }}>
        {items.map(item => {
          const isActive = active === item.key;
          return (
            <button key={item.key} onClick={() => onChange(item.key)} style={{
              flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 2,
              border: 0, background: "transparent",
              color: isActive ? "var(--accent)" : "var(--fg-muted)",
              cursor: "pointer", fontFamily: "inherit",
            }}>
              <Icon name={item.icon} size={22}/>
              <span style={{ fontSize: 10, fontWeight: 500 }}>{item.label}</span>
            </button>
          );
        })}
      </div>
      {/* safe-area spacer for iPhone home indicator */}
      <div style={{ height: "env(safe-area-inset-bottom, 0px)", background: "inherit" }}/>
    </div>
  );
}

// ── MobileTopBar ──────────────────────────────────────────────────
function MobileTopBar({ title, right }) {
  return (
    <div style={{
      display: "flex", alignItems: "flex-end", padding: "0 16px 0",
      paddingTop: "env(safe-area-inset-top, 0px)",
      minHeight: "calc(52px + env(safe-area-inset-top, 0px))",
      borderBottom: "1px solid var(--border-subtle)", background: "var(--bg-panel)",
      flexShrink: 0,
    }}>
      <div style={{ display: "flex", alignItems: "center", width: "100%", height: 52 }}>
        <h1 style={{ flex: 1, fontSize: 16, fontWeight: 600, color: "var(--fg-primary)", margin: 0 }}>{title}</h1>
        {right}
      </div>
    </div>
  );
}

// ── Toast ─────────────────────────────────────────────────────────
function ToastContainer({ toasts }) {
  return (
    <div className="toast-wrap">
      {toasts.map(t => (
        <div key={t.id} className={`toast toast-${t.type}`}>{t.message}</div>
      ))}
    </div>
  );
}

// ── Loading skeleton row ──────────────────────────────────────────
function SkeletonRows({ n = 8 }) {
  return (
    <div style={{ padding: "8px 24px", display: "flex", flexDirection: "column", gap: 1 }}>
      {Array.from({ length: n }).map((_, i) => (
        <div key={i} className="skeleton" style={{ height: 46, marginBottom: 1 }}/>
      ))}
    </div>
  );
}

// ── Empty state ───────────────────────────────────────────────────
function EmptyState({ icon = "inbox", message = "Нічого не знайдено", action }) {
  return (
    <div style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 12, color: "var(--fg-muted)", padding: 48 }}>
      <Icon name={icon} size={48} style={{ opacity: 0.25 }}/>
      <p style={{ fontSize: 14, color: "var(--fg-muted)", margin: 0 }}>{message}</p>
      {action}
    </div>
  );
}

// ── Messenger badges ──────────────────────────────────────────────
const MSG_BRANDS = {
  telegram: { color: "#229ED9", svg: <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm5.6 8.2-1.9 8.9c-.1.6-.5.8-1.1.5l-3-2.2-1.4 1.4c-.2.2-.3.3-.6.3l.2-3 5.6-5c.2-.2 0-.3-.3-.1l-6.9 4.3-3-.9c-.6-.2-.6-.6.1-.9l11.7-4.5c.5-.2 1 .1.6 1.2z"/></svg> },
  viber:    { color: "#7360F2", svg: <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M11.4 0c-.7 0-2.7.1-4.1.6C5 1.4 4 2.7 3.5 4.4 3 6.1 3 7.8 3 9.6c0 1.7.1 3.5.5 5 .5 1.7 1.4 3 3.7 3.6.4.1.5.2.5.6v1.7c0 .4.3.5.6.3l2-1.6c.2-.2.4-.2.7-.2 1.5.1 3.2 0 4.7-.4 1.7-.5 2.7-1.6 3.2-3.3.4-1.5.5-3.2.5-5 0-1.7 0-3.5-.5-5-.5-1.7-1.6-3-3.4-3.5C13.9 0 12.4 0 11.4 0z"/></svg> },
  whatsapp: { color: "#25D366", svg: <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.4 0 0 5.4 0 12c0 2.1.6 4.2 1.6 6L0 24l6.2-1.6c1.8.9 3.7 1.4 5.8 1.4 6.6 0 12-5.4 12-12S18.6 0 12 0zm6.7 17c-.3.8-1.6 1.5-2.2 1.6-.6.1-1.3.1-2.1-.1-.5-.2-1.1-.4-1.9-.7-3.4-1.5-5.6-4.9-5.7-5.1-.2-.2-1.4-1.9-1.4-3.6s.9-2.5 1.2-2.9c.3-.3.7-.4.9-.4h.7c.2 0 .5 0 .8.6.3.7 1 2.4 1.1 2.6.1.2.1.4 0 .6-.1.2-.2.3-.4.5-.2.2-.4.5-.5.6-.2.2-.4.4-.2.7.2.4.9 1.5 1.9 2.4 1.3 1.2 2.4 1.5 2.7 1.7.3.1.5.1.7-.1.2-.2.8-.9 1-1.2.2-.3.4-.3.7-.2.3.1 2 1 2.3 1.1.3.2.5.2.6.4 0 .1 0 .8-.3 1.5z"/></svg> },
};

function MessengerBtn({ kind, phone }) {
  const m = MSG_BRANDS[kind];
  if (!m) return null;

  let href = null;
  if (phone && phone !== "—") {
    const digits = phone.replace(/\D/g, "");
    const intl = digits.startsWith("38") && digits.length === 12
      ? digits
      : "38" + (digits.startsWith("0") ? digits.slice(1) : digits);
    if (kind === "viber")    href = `viber://chat?number=%2B${intl}`;
    if (kind === "whatsapp") href = `https://wa.me/${intl}`;
    if (kind === "telegram") href = `https://t.me/%2B${intl}`;
  }

  const inner = (
    <span title={kind[0].toUpperCase() + kind.slice(1)} style={{
      width: 28, height: 28, borderRadius: 6, display: "inline-flex", alignItems: "center", justifyContent: "center",
      background: `${m.color}22`, color: m.color, flexShrink: 0, cursor: href ? "pointer" : "default",
    }}>
      {React.cloneElement(m.svg, { width: 14, height: 14 })}
    </span>
  );

  if (href) return <a href={href} target="_blank" rel="noreferrer" style={{ textDecoration: "none", display: "inline-flex" }}>{inner}</a>;
  return inner;
}

// ── Paid badge ────────────────────────────────────────────────────
function PaidBadge({ payed }) {
  return payed == 1
    ? <span style={{ display: "inline-flex", alignItems: "center", gap: 4, height: 18, padding: "0 6px", borderRadius: 4, background: "rgba(16,185,129,.14)", color: "var(--credit)", fontSize: 11, fontWeight: 500 }}>Оплачено</span>
    : <span style={{ display: "inline-flex", alignItems: "center", gap: 4, height: 18, padding: "0 6px", borderRadius: 4, background: "rgba(245,158,11,.14)", color: "var(--warning)", fontSize: 11, fontWeight: 500 }}>Не оплачено</span>;
}

// ── Call utilities (shared with Orders.jsx) ───────────────────────
function fmtDur(sec) {
  const s = Number(sec) || 0;
  return `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}`;
}
function fmtCallDate(str) {
  if (!str) return '—';
  const d = new Date(str.replace(' ', 'T'));
  if (isNaN(d)) return str;
  const now  = new Date();
  const dDay = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
  const tDay = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
  const time = d.toTimeString().slice(0, 5);
  if (dDay === tDay)            return `Сьогодні, ${time}`;
  if (dDay === tDay - 86400000) return `Вчора, ${time}`;
  return `${String(d.getDate()).padStart(2,'0')}.${String(d.getMonth()+1).padStart(2,'0')}.${d.getFullYear()}, ${time}`;
}
const CALL_DISP_COLOR = {
  ANSWERED: 'var(--credit)', 'NO ANSWER': '#ef4444',
  MISSED: '#ef4444', BUSY: '#f59e0b', FAILED: '#ef4444',
};
function CallPlayer({ recording, playing, onToggle, progress }) {
  if (!recording) return <span style={{ fontSize: 11, color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>—</span>;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10, width: '100%' }}>
      <button onClick={onToggle} style={{
        width: 30, height: 30, borderRadius: '50%',
        background: playing ? 'var(--accent)' : 'var(--bg-raised)',
        border: playing ? 0 : '1px solid var(--border-default)',
        display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexShrink: 0,
      }}>
        <Icon name={playing ? 'pause' : 'play'} size={12} color={playing ? '#fff' : 'var(--fg-primary)'}/>
      </button>
      <div style={{ position: 'relative', flex: 1, height: 4, background: 'var(--border-strong)', borderRadius: 2, overflow: 'hidden' }}>
        <div style={{ position: 'absolute', left: 0, top: 0, height: '100%', width: `${progress}%`, background: 'var(--accent)', borderRadius: 2, transition: 'width 100ms linear' }}/>
      </div>
    </div>
  );
}

Object.assign(window, {
  LangCtx,
  STATUSES, HOROSHOP_STATUS_MAP,
  fmtDate, fmtPhone, fmtMoney, fmtBalance,
  fmtDur, fmtCallDate, CALL_DISP_COLOR, CallPlayer,
  Icon, StatusChip, Button, Avatar, BankMonogram,
  Sidebar, TopBar, BottomTabs, MobileTopBar,
  ToastContainer, SkeletonRows, EmptyState,
  MessengerBtn, PaidBadge,
  useState, useEffect, useRef, useCallback,
});
