"use client";

// ============================================================
// LynkedUp Pro — shared design-system primitives.
// Tokens live in dashboard.css (.dash-root). These components
// only consume CSS variables so they theme automatically.
//
// Exports: Icon, Avatar, PageHead, Pill, Toggle, OtpField,
//          Modal, ToastProvider/useToast, Field, SegTabs,
//          StatusDot, Segmented.
// ============================================================

import {
  createContext, useCallback, useContext, useEffect, useId,
  useRef, useState, type ReactNode,
} from "react";
import { createPortal } from "react-dom";
import {
  MessageCircle, Ticket, Phone, Mail, BookOpen, Rocket, Shield, ShieldCheck,
  Lock, CreditCard, User, Bell, Eye, EyeOff, Camera, Upload, Plus, Star, Send,
  Paperclip, Clock, MapPin, Monitor, Smartphone, Tablet, LogOut, ArrowRight,
  Info, Check, X, Search, ChevronDown, ChevronRight, Trash2, Globe,
  CheckCircle2, KeyRound, Pencil, Copy, RefreshCw, AlertTriangle,
  LayoutDashboard, Building2, FolderKanban, UserPlus, BadgeCheck, Filter,
  Truck, CloudLightning, Map as MapIcon, PenTool, Calculator, CalendarDays,
  Trophy, ListChecks, Users, Settings, Sparkles, MoreHorizontal,
  UsersRound, Image as ImageIcon, Images, File, FolderOpen, Download,
  Video, Play, LayoutGrid, ZoomIn, type LucideIcon,
} from "lucide-react";

/* ---------------------------------------------------------- */
/* Icon — single named entry point used across the module      */
/* ---------------------------------------------------------- */

const ICONS: Record<string, LucideIcon> = {
  chat: MessageCircle, ticket: Ticket, phone: Phone, mail: Mail, book: BookOpen,
  rocket: Rocket, shield: Shield, "shield-check": ShieldCheck, lock: Lock,
  card: CreditCard, user: User, bell: Bell, eye: Eye, "eye-off": EyeOff,
  camera: Camera, upload: Upload, plus: Plus, star: Star, send: Send,
  paperclip: Paperclip, clock: Clock, pin: MapPin, monitor: Monitor,
  mobile: Smartphone, tablet: Tablet, logout: LogOut, arrow: ArrowRight,
  info: Info, check: Check, x: X, search: Search, chevron: ChevronDown,
  "chevron-right": ChevronRight, trash: Trash2, globe: Globe,
  "check-circle": CheckCircle2, key: KeyRound, edit: Pencil, copy: Copy,
  refresh: RefreshCw, alert: AlertTriangle, privacy: ShieldCheck, devices: Monitor,
  desktop: Monitor,
  // sidebar / workspace nav
  dashboard: LayoutDashboard, owners: Building2, projects: FolderKanban,
  leads: UserPlus, verify: BadgeCheck, pipeline: Filter, dispatch: Truck,
  storm: CloudLightning, territory: MapIcon, procanvas: PenTool,
  estimates: Calculator, schedule: CalendarDays, leaderboard: Trophy,
  subtasks: ListChecks, people: Users, settings: Settings, ai: Sparkles,
  team: UsersRound, dots: MoreHorizontal,
  // media / gallery (also used by messenger.tsx, which already asks for image/file)
  image: ImageIcon, gallery: Images, file: File, folder: FolderOpen,
  download: Download, video: Video, play: Play, grid: LayoutGrid,
  filter: Filter, zoom: ZoomIn, sparkle: Sparkles, "map-pin": MapPin,
};

export function Icon({ name, size = 18, className, strokeWidth = 2 }: { name: string; size?: number; className?: string; strokeWidth?: number }) {
  const C = ICONS[name] ?? Info;
  return <C size={size} className={className} strokeWidth={strokeWidth} />;
}

/* ---------------------------------------------------------- */
/* Avatar                                                      */
/* ---------------------------------------------------------- */

export function Avatar({
  initials, gradient = "linear-gradient(135deg,#fda913,#fd6d13)", size = 40, status, square = false,
}: { initials: string; gradient?: string; size?: number; status?: "online" | "away" | "offline" | "busy"; square?: boolean }) {
  return (
    <span className="ds-avatar" style={{ width: size, height: size, borderRadius: square ? size * 0.28 : "50%", fontSize: size * 0.36 }}>
      <span className="ds-avatar-bg" style={{ background: gradient, borderRadius: "inherit" }}>{initials}</span>
      {status && <span className={`ds-avatar-dot status-${status}`} style={{ width: size * 0.28, height: size * 0.28 }} />}
    </span>
  );
}

/* ---------------------------------------------------------- */
/* PageHead — section title block used at the top of each view */
/* ---------------------------------------------------------- */

export function PageHead({ eyebrow, title, subtitle, icon, actions }: { eyebrow?: string; title: string; subtitle?: string; icon?: string; actions?: ReactNode }) {
  return (
    <div className="ds-pagehead">
      <div className="ds-pagehead-l">
        {icon && <span className="ds-pagehead-ic"><Icon name={icon} size={22} /></span>}
        <div>
          {eyebrow && <div className="ds-eyebrow">{eyebrow}</div>}
          <h1>{title}</h1>
          {subtitle && <p>{subtitle}</p>}
        </div>
      </div>
      {actions && <div className="ds-pagehead-actions">{actions}</div>}
    </div>
  );
}

/* ---------------------------------------------------------- */
/* Pill / StatusDot                                            */
/* ---------------------------------------------------------- */

export function Pill({ children, tone = "muted", style }: { children: ReactNode; tone?: string; style?: React.CSSProperties }) {
  return <span className={`ds-pill tone-${tone}`} style={style}>{children}</span>;
}

export function StatusDot({ status }: { status: "online" | "away" | "offline" | "busy" }) {
  return <span className={`ds-statusdot status-${status}`} />;
}

/* ---------------------------------------------------------- */
/* Toggle                                                      */
/* ---------------------------------------------------------- */

export function Toggle({ checked, onChange, disabled, label }: { checked: boolean; onChange?: (v: boolean) => void; disabled?: boolean; label?: string }) {
  return (
    <button
      type="button" role="switch" aria-checked={checked} aria-label={label}
      className={`ds-toggle ${checked ? "on" : ""} ${disabled ? "disabled" : ""}`}
      onClick={() => !disabled && onChange?.(!checked)}
      disabled={disabled}
    >
      <span className="knob" />
    </button>
  );
}

/* ---------------------------------------------------------- */
/* Field — labelled input wrapper                              */
/* ---------------------------------------------------------- */

export function Field({ label, hint, error, children, required }: { label: string; hint?: string; error?: string; children: ReactNode; required?: boolean }) {
  return (
    <label className="ds-field">
      <span className="ds-field-lbl">{label}{required && <i className="req">*</i>}</span>
      {children}
      {error ? <span className="ds-field-err"><Icon name="alert" size={12} /> {error}</span> : hint ? <span className="ds-field-hint">{hint}</span> : null}
    </label>
  );
}

/* ---------------------------------------------------------- */
/* Segmented / SegTabs                                         */
/* ---------------------------------------------------------- */

export function Segmented({ options, value, onChange }: { options: { value: string; label: string; icon?: string }[]; value: string; onChange: (v: string) => void }) {
  return (
    <div className="ds-segmented" role="tablist">
      {options.map((o) => (
        <button key={o.value} role="tab" aria-selected={value === o.value} className={`seg ${value === o.value ? "active" : ""}`} onClick={() => onChange(o.value)}>
          {o.icon && <Icon name={o.icon} size={15} />} {o.label}
        </button>
      ))}
    </div>
  );
}

export function SegTabs({ tabs, value, onChange }: { tabs: { value: string; label: string; icon?: string; badge?: number }[]; value: string; onChange: (v: string) => void }) {
  return (
    <div className="ds-tabs" role="tablist">
      {tabs.map((t) => (
        <button key={t.value} role="tab" aria-selected={value === t.value} className={`ds-tab ${value === t.value ? "active" : ""}`} onClick={() => onChange(t.value)}>
          {t.icon && <Icon name={t.icon} size={16} />}
          <span>{t.label}</span>
          {t.badge != null && t.badge > 0 && <span className="ds-tab-badge">{t.badge}</span>}
        </button>
      ))}
    </div>
  );
}

/* ---------------------------------------------------------- */
/* OtpField — N-digit one-time-code input                      */
/* ---------------------------------------------------------- */

export function OtpField({ length = 6, value, onChange, autoFocus = true }: { length?: number; value: string; onChange: (v: string) => void; autoFocus?: boolean }) {
  const refs = useRef<(HTMLInputElement | null)[]>([]);
  useEffect(() => { if (autoFocus) refs.current[0]?.focus(); }, [autoFocus]);

  function setAt(i: number, char: string) {
    const next = value.split("");
    next[i] = char;
    const joined = next.join("").slice(0, length);
    onChange(joined);
  }

  return (
    <div className="ds-otp">
      {Array.from({ length }).map((_, i) => (
        <input
          key={i}
          ref={(el) => { refs.current[i] = el; }}
          inputMode="numeric"
          maxLength={1}
          className="ds-otp-box"
          value={value[i] ?? ""}
          onChange={(e) => {
            const d = e.target.value.replace(/\D/g, "");
            if (!d) { setAt(i, ""); return; }
            // support paste of full code
            if (d.length > 1) {
              onChange((value.slice(0, i) + d).slice(0, length));
              refs.current[Math.min(i + d.length, length - 1)]?.focus();
              return;
            }
            setAt(i, d);
            refs.current[Math.min(i + 1, length - 1)]?.focus();
          }}
          onKeyDown={(e) => {
            if (e.key === "Backspace" && !value[i] && i > 0) refs.current[i - 1]?.focus();
            if (e.key === "ArrowLeft" && i > 0) refs.current[i - 1]?.focus();
            if (e.key === "ArrowRight" && i < length - 1) refs.current[i + 1]?.focus();
          }}
        />
      ))}
    </div>
  );
}

/* ---------------------------------------------------------- */
/* Modal                                                       */
/* ---------------------------------------------------------- */

export function Modal({ open, onClose, title, subtitle, icon, children, footer, size = "md", headerExtra }: {
  open: boolean; onClose: () => void; title: string; subtitle?: ReactNode; icon?: string;
  children: ReactNode; footer?: ReactNode; size?: "sm" | "md" | "lg" | "xl"; headerExtra?: ReactNode;
}) {
  const titleId = useId();
  // Portal the overlay up to `.dash-root` so its position:fixed anchors to the viewport,
  // not to a transformed/overflow panel ancestor (which would clip or offset the modal).
  const [host, setHost] = useState<Element | null>(null);
  const [mounted, setMounted] = useState(false);
  useEffect(() => { setHost(document.querySelector(".dash-root")); setMounted(true); }, []);
  useEffect(() => {
    if (!open) return;
    const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [open, onClose]);

  if (!open || !mounted) return null;
  const overlay = (
    <div className="ds-modal-overlay" onMouseDown={onClose}>
      <div className={`ds-modal size-${size}`} role="dialog" aria-modal="true" aria-labelledby={titleId} onMouseDown={(e) => e.stopPropagation()}>
        <div className="ds-modal-head">
          <div className="ds-modal-head-l">
            {icon && <span className="ds-modal-ic"><Icon name={icon} size={18} /></span>}
            <div>
              <h3 id={titleId}>{title}</h3>
              {subtitle && <p>{subtitle}</p>}
            </div>
          </div>
          <div className="ds-modal-head-r">
            {headerExtra}
            <button className="ds-iconbtn" aria-label="Close" onClick={onClose}><Icon name="x" size={18} /></button>
          </div>
        </div>
        <div className="ds-modal-body">{children}</div>
        {footer && <div className="ds-modal-foot">{footer}</div>}
      </div>
    </div>
  );
  return host ? createPortal(overlay, host) : overlay;
}

/* ---------------------------------------------------------- */
/* Toast                                                       */
/* ---------------------------------------------------------- */

type Toast = { id: number; tone: "success" | "info" | "error"; title: string; desc?: string; onClick?: () => void };
type ToastCtx = { push: (t: Omit<Toast, "id">) => void };
const ToastContext = createContext<ToastCtx | null>(null);

export function useToast() {
  const ctx = useContext(ToastContext);
  if (!ctx) return { push: () => {} };
  return ctx;
}

let toastSeq = 1;
export function ToastProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<Toast[]>([]);
  const push = useCallback((t: Omit<Toast, "id">) => {
    const id = toastSeq++;
    setItems((s) => [...s, { ...t, id }]);
    setTimeout(() => setItems((s) => s.filter((x) => x.id !== id)), 3800);
  }, []);
  return (
    <ToastContext.Provider value={{ push }}>
      {children}
      <div className="ds-toasts">
        {items.map((t) => (
          <div key={t.id} className={`ds-toast tone-${t.tone}${t.onClick ? " is-clickable" : ""}`}>
            <Icon name={t.tone === "success" ? "check-circle" : t.tone === "error" ? "alert" : "info"} size={18} />
            <div
              className="ds-toast-body"
              {...(t.onClick ? { role: "button", tabIndex: 0, onClick: () => { t.onClick?.(); setItems((s) => s.filter((x) => x.id !== t.id)); } } : {})}
            >
              <div className="ds-toast-title">{t.title}</div>
              {t.desc && <div className="ds-toast-desc">{t.desc}</div>}
            </div>
            <button className="ds-toast-x" aria-label="Dismiss" onClick={() => setItems((s) => s.filter((x) => x.id !== t.id))}><Icon name="x" size={14} /></button>
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

/* ---------------------------------------------------------- */
/* Button — light helper so call sites stay terse              */
/* ---------------------------------------------------------- */

export function Btn({ children, variant = "primary", icon, iconRight, onClick, disabled, type = "button", full, size = "md" }: {
  children: ReactNode; variant?: "primary" | "ghost" | "soft" | "danger" | "outline";
  icon?: string; iconRight?: string; onClick?: () => void; disabled?: boolean;
  type?: "button" | "submit"; full?: boolean; size?: "sm" | "md";
}) {
  return (
    <button type={type} className={`ds-btn v-${variant} s-${size} ${full ? "full" : ""}`} onClick={onClick} disabled={disabled}>
      {icon && <Icon name={icon} size={size === "sm" ? 14 : 16} />}
      {children}
      {iconRight && <Icon name={iconRight} size={size === "sm" ? 14 : 16} />}
    </button>
  );
}
