"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ButtonHTMLAttributes,
  type InputHTMLAttributes,
  type ReactNode,
  type SelectHTMLAttributes,
  type TextareaHTMLAttributes,
} from "react";
import { CheckCircle2, Info, Loader2, TriangleAlert, X, XCircle } from "lucide-react";
import { STATUS_COLORS, classNames, humanLabel } from "@/lib/utils";

export const cn = classNames;

/* --------------------------------- button -------------------------------- */

type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success" | "outline";

const buttonStyles: Record<ButtonVariant, string> = {
  primary: "bg-gradient-to-r from-brand-500 to-brand-600 text-white hover:from-brand-400 hover:to-brand-500 shadow-lg shadow-brand-600/20",
  secondary: "bg-white/8 text-slate-100 hover:bg-white/14 border border-white/10",
  ghost: "text-slate-300 hover:bg-white/8",
  danger: "bg-rose-500/90 text-white hover:bg-rose-500",
  success: "bg-emerald-500/90 text-white hover:bg-emerald-500",
  outline: "border border-brand-400/40 text-brand-400 hover:bg-brand-500/10",
};

export function Button({
  variant = "primary",
  size = "md",
  loading = false,
  icon,
  className,
  children,
  ...props
}: ButtonHTMLAttributes<HTMLButtonElement> & {
  variant?: ButtonVariant;
  size?: "sm" | "md" | "lg";
  loading?: boolean;
  icon?: ReactNode;
}) {
  return (
    <button
      {...props}
      disabled={props.disabled || loading}
      className={cn(
        "inline-flex items-center justify-center gap-2 rounded-lg font-medium transition-all duration-150 disabled:cursor-not-allowed disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400/60",
        size === "sm" ? "px-2.5 py-1.5 text-xs" : size === "lg" ? "px-5 py-2.5 text-sm" : "px-3.5 py-2 text-sm",
        buttonStyles[variant],
        className,
      )}
    >
      {loading ? <Loader2 className="h-4 w-4 animate-spin" /> : icon}
      {children}
    </button>
  );
}

/* ---------------------------------- card --------------------------------- */

export function Card({ className, children, ...rest }: { className?: string; children: ReactNode } & React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div {...rest} className={cn("glass rounded-2xl", className)}>
      {children}
    </div>
  );
}

export function CardHeader({
  title,
  subtitle,
  action,
  icon,
}: {
  title: ReactNode;
  subtitle?: ReactNode;
  action?: ReactNode;
  icon?: ReactNode;
}) {
  return (
    <div className="flex flex-wrap items-center justify-between gap-3 border-b border-white/8 px-4 py-3 sm:px-5">
      <div className="flex items-center gap-3">
        {icon ? <span className="grid h-9 w-9 place-items-center rounded-xl bg-brand-500/15 text-brand-400">{icon}</span> : null}
        <div>
          <h3 className="text-sm font-semibold text-slate-100">{title}</h3>
          {subtitle ? <p className="text-xs text-slate-400">{subtitle}</p> : null}
        </div>
      </div>
      {action}
    </div>
  );
}

export function StatCard({
  label,
  value,
  icon,
  tone = "brand",
  hint,
  onClick,
}: {
  label: string;
  value: ReactNode;
  icon?: ReactNode;
  tone?: "brand" | "green" | "amber" | "rose" | "cyan" | "violet" | "slate";
  hint?: ReactNode;
  onClick?: () => void;
}) {
  const tones: Record<string, string> = {
    brand: "from-brand-500/22 to-brand-500/5 text-brand-400",
    green: "from-emerald-500/22 to-emerald-500/5 text-emerald-400",
    amber: "from-amber-500/22 to-amber-500/5 text-amber-400",
    rose: "from-rose-500/22 to-rose-500/5 text-rose-400",
    cyan: "from-cyan-500/22 to-cyan-500/5 text-cyan-300",
    violet: "from-violet-500/22 to-violet-500/5 text-violet-300",
    slate: "from-slate-400/20 to-slate-400/5 text-slate-300",
  };
  return (
    <div
      onClick={onClick}
      className={cn(
        "glass hover-lift relative overflow-hidden rounded-2xl p-4",
        onClick && "cursor-pointer",
      )}
    >
      <div className={cn("pointer-events-none absolute -right-6 -top-8 h-24 w-24 rounded-full bg-gradient-to-br blur-2xl", tones[tone])} />
      <div className="flex items-start justify-between gap-2">
        <div className="min-w-0">
          <p className="truncate text-[11px] font-semibold uppercase tracking-wider text-slate-400">{label}</p>
          <p className="mt-1.5 truncate text-xl font-semibold text-slate-50 sm:text-2xl">{value}</p>
          {hint ? <p className="mt-1 text-[11px] text-slate-400">{hint}</p> : null}
        </div>
        {icon ? <span className={cn("grid h-10 w-10 shrink-0 place-items-center rounded-xl bg-white/6", tones[tone].split(" ").pop())}>{icon}</span> : null}
      </div>
    </div>
  );
}

/* --------------------------------- badge --------------------------------- */

export function Badge({ value, className, label }: { value?: string | null; className?: string; label?: string }) {
  const key = (value ?? "").toLowerCase();
  const text = label ?? humanLabel(key || "n/a");
  return (
    <span className={cn("inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-semibold ring-1 ring-inset", STATUS_COLORS[key] ?? "bg-slate-500/15 text-slate-300 ring-slate-500/25", className)}>
      {key === "online" || key === "active" ? <span className="pulse-dot h-1.5 w-1.5 rounded-full bg-emerald-400" /> : null}
      {text}
    </span>
  );
}

/* --------------------------------- fields -------------------------------- */

export function Field({ label, hint, error, children, className }: { label?: string; hint?: string; error?: string; children: ReactNode; className?: string }) {
  return (
    <div className={className}>
      {label ? <label className="label">{label}</label> : null}
      {children}
      {error ? <p className="mt-1 text-[11px] text-rose-400">{error}</p> : hint ? <p className="mt-1 text-[11px] text-slate-500">{hint}</p> : null}
    </div>
  );
}

export function Input({ className, ...props }: InputHTMLAttributes<HTMLInputElement>) {
  return <input {...props} className={cn("field", className)} />;
}

export function Select({ className, children, ...props }: SelectHTMLAttributes<HTMLSelectElement>) {
  return (
    <select {...props} className={cn("field", className)}>
      {children}
    </select>
  );
}

export function Textarea({ className, ...props }: TextareaHTMLAttributes<HTMLTextAreaElement>) {
  return <textarea {...props} className={cn("field min-h-24", className)} />;
}

/* --------------------------------- modal --------------------------------- */

export function Modal({
  open,
  onClose,
  title,
  subtitle,
  children,
  footer,
  size = "md",
}: {
  open: boolean;
  onClose: () => void;
  title: ReactNode;
  subtitle?: ReactNode;
  children: ReactNode;
  footer?: ReactNode;
  size?: "sm" | "md" | "lg" | "xl";
}) {
  useEffect(() => {
    if (!open) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [open, onClose]);

  if (!open) return null;
  const widths = { sm: "max-w-md", md: "max-w-2xl", lg: "max-w-4xl", xl: "max-w-6xl" };
  return (
    <div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-ink-950/80 p-3 backdrop-blur-sm sm:p-6">
      <div className={cn("glass-strong animate-fade-up my-auto w-full rounded-2xl", widths[size])}>
        <div className="flex items-start justify-between gap-4 border-b border-white/10 px-5 py-4">
          <div>
            <h3 className="text-base font-semibold text-slate-50">{title}</h3>
            {subtitle ? <p className="mt-0.5 text-xs text-slate-400">{subtitle}</p> : null}
          </div>
          <button onClick={onClose} className="rounded-lg p-1.5 text-slate-400 transition hover:bg-white/10 hover:text-slate-100" aria-label="Close">
            <X className="h-4 w-4" />
          </button>
        </div>
        <div className="max-h-[70vh] overflow-y-auto px-5 py-4">{children}</div>
        {footer ? <div className="flex flex-wrap items-center justify-end gap-2 border-t border-white/10 px-5 py-3">{footer}</div> : null}
      </div>
    </div>
  );
}

/* --------------------------------- table --------------------------------- */

export interface Column<T> {
  key: string;
  label: string;
  render?: (row: T) => ReactNode;
  className?: string;
  hideOnMobile?: boolean;
}

export function DataTable<T extends Record<string, unknown>>({
  columns,
  rows,
  loading,
  empty = "No records found",
  rowKey,
  onRowClick,
  selectable,
  selected,
  onSelect,
}: {
  columns: Column<T>[];
  rows: T[];
  loading?: boolean;
  empty?: string;
  rowKey: (row: T) => string | number;
  onRowClick?: (row: T) => void;
  selectable?: boolean;
  selected?: Set<string | number>;
  onSelect?: (ids: Set<string | number>) => void;
}) {
  const allSelected = selectable && rows.length > 0 && rows.every((r) => selected?.has(rowKey(r)));
  return (
    <div className="table-wrap">
      <table className="data">
        <thead>
          <tr>
            {selectable ? (
              <th className="w-10">
                <input
                  type="checkbox"
                  className="h-4 w-4 accent-brand-500"
                  checked={Boolean(allSelected)}
                  onChange={(e) => {
                    const next = new Set(selected);
                    if (e.target.checked) rows.forEach((r) => next.add(rowKey(r)));
                    else rows.forEach((r) => next.delete(rowKey(r)));
                    onSelect?.(next);
                  }}
                />
              </th>
            ) : null}
            {columns.map((col) => (
              <th key={col.key} className={col.hideOnMobile ? "hidden md:table-cell" : undefined}>
                {col.label}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {loading ? (
            Array.from({ length: 6 }).map((_, i) => (
              <tr key={i}>
                <td colSpan={columns.length + (selectable ? 1 : 0)} className="py-3">
                  <div className="skeleton h-4 w-full rounded" />
                </td>
              </tr>
            ))
          ) : rows.length === 0 ? (
            <tr>
              <td colSpan={columns.length + (selectable ? 1 : 0)} className="py-10 text-center text-sm text-slate-500">
                {empty}
              </td>
            </tr>
          ) : (
            rows.map((row) => (
              <tr key={rowKey(row)} onClick={() => onRowClick?.(row)} className={onRowClick ? "cursor-pointer" : undefined}>
                {selectable ? (
                  <td onClick={(e) => e.stopPropagation()}>
                    <input
                      type="checkbox"
                      className="h-4 w-4 accent-brand-500"
                      checked={selected?.has(rowKey(row)) ?? false}
                      onChange={(e) => {
                        const next = new Set(selected);
                        if (e.target.checked) next.add(rowKey(row));
                        else next.delete(rowKey(row));
                        onSelect?.(next);
                      }}
                    />
                  </td>
                ) : null}
                {columns.map((col) => (
                  <td key={col.key} className={col.className ?? col.hideOnMobile ? cn(col.className, "hidden md:table-cell") : col.className}>
                    {col.render ? col.render(row) : String(row[col.key] ?? "—")}
                  </td>
                ))}
              </tr>
            ))
          )}
        </tbody>
      </table>
    </div>
  );
}

export function Pagination({
  page,
  pages,
  total,
  onChange,
}: {
  page: number;
  pages: number;
  total: number;
  onChange: (page: number) => void;
}) {
  if (pages <= 1) return <p className="px-1 py-2 text-xs text-slate-500">{total} record(s)</p>;
  return (
    <div className="flex flex-wrap items-center justify-between gap-2 px-1 py-2 text-xs text-slate-400">
      <span>
        Page {page} of {pages} · {total} record(s)
      </span>
      <div className="flex items-center gap-1">
        <Button variant="secondary" size="sm" disabled={page <= 1} onClick={() => onChange(page - 1)}>
          Prev
        </Button>
        <Button variant="secondary" size="sm" disabled={page >= pages} onClick={() => onChange(page + 1)}>
          Next
        </Button>
      </div>
    </div>
  );
}

/* ---------------------------------- tabs --------------------------------- */

export function Tabs<T extends string>({ tabs, value, onChange }: { tabs: { value: T; label: string; icon?: ReactNode }[]; value: T; onChange: (v: T) => void }) {
  return (
    <div className="flex gap-1 overflow-x-auto rounded-xl border border-white/8 bg-white/4 p-1">
      {tabs.map((tab) => (
        <button
          key={tab.value}
          onClick={() => onChange(tab.value)}
          className={cn(
            "flex shrink-0 items-center gap-2 rounded-lg px-3 py-1.5 text-xs font-medium transition",
            value === tab.value ? "bg-brand-500/20 text-brand-400 ring-1 ring-inset ring-brand-400/30" : "text-slate-400 hover:bg-white/6 hover:text-slate-200",
          )}
        >
          {tab.icon}
          {tab.label}
        </button>
      ))}
    </div>
  );
}

/* ------------------------------- page header ----------------------------- */

export function PageHeader({ title, subtitle, actions, icon }: { title: string; subtitle?: string; actions?: ReactNode; icon?: ReactNode }) {
  return (
    <div className="mb-5 flex flex-wrap items-center justify-between gap-3">
      <div className="flex items-center gap-3">
        {icon ? <span className="grid h-11 w-11 place-items-center rounded-xl bg-brand-500/15 text-brand-400">{icon}</span> : null}
        <div>
          <h1 className="text-lg font-semibold text-slate-50 sm:text-xl">{title}</h1>
          {subtitle ? <p className="text-xs text-slate-400 sm:text-sm">{subtitle}</p> : null}
        </div>
      </div>
      {actions ? <div className="flex flex-wrap items-center gap-2">{actions}</div> : null}
    </div>
  );
}

/* --------------------------------- toasts -------------------------------- */

type ToastKind = "success" | "error" | "info" | "warning";
interface ToastItem {
  id: number;
  kind: ToastKind;
  message: string;
}

const ToastContext = createContext<{ push: (message: string, kind?: ToastKind) => void }>({ push: () => {} });

export function ToastProvider({ children }: { children: ReactNode }) {
  const [items, setItems] = useState<ToastItem[]>([]);
  const push = useCallback((message: string, kind: ToastKind = "info") => {
    const id = Date.now() + Math.random();
    setItems((prev) => [...prev, { id, kind, message }]);
    setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 4200);
  }, []);
  const value = useMemo(() => ({ push }), [push]);
  const icons: Record<ToastKind, ReactNode> = {
    success: <CheckCircle2 className="h-4 w-4 text-emerald-400" />,
    error: <XCircle className="h-4 w-4 text-rose-400" />,
    warning: <TriangleAlert className="h-4 w-4 text-amber-400" />,
    info: <Info className="h-4 w-4 text-brand-400" />,
  };
  return (
    <ToastContext.Provider value={value}>
      {children}
      <div className="pointer-events-none fixed bottom-4 right-4 z-[60] flex w-[min(92vw,22rem)] flex-col gap-2">
        {items.map((item) => (
          <div key={item.id} className="glass-strong animate-fade-up pointer-events-auto flex items-start gap-2 rounded-xl px-3.5 py-2.5 text-sm text-slate-100">
            {icons[item.kind]}
            <span className="flex-1">{item.message}</span>
            <button onClick={() => setItems((prev) => prev.filter((t) => t.id !== item.id))} className="text-slate-500 hover:text-slate-200">
              <X className="h-3.5 w-3.5" />
            </button>
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

export const useToast = () => useContext(ToastContext);

/* ------------------------------- misc pieces ----------------------------- */

export function Spinner({ className }: { className?: string }) {
  return <Loader2 className={cn("h-5 w-5 animate-spin text-brand-400", className)} />;
}

export function KeyValue({ items }: { items: { label: string; value: ReactNode }[] }) {
  return (
    <dl className="grid grid-cols-1 gap-x-6 gap-y-3 sm:grid-cols-2 lg:grid-cols-3">
      {items.map((item) => (
        <div key={item.label} className="min-w-0">
          <dt className="text-[11px] uppercase tracking-wide text-slate-500">{item.label}</dt>
          <dd className="mt-0.5 truncate text-sm text-slate-100">{item.value ?? "—"}</dd>
        </div>
      ))}
    </dl>
  );
}

export function ErrorNote({ message }: { message?: string | null }) {
  if (!message) return null;
  return (
    <div className="flex items-start gap-2 rounded-xl border border-rose-500/25 bg-rose-500/10 px-3 py-2 text-xs text-rose-200">
      <XCircle className="mt-0.5 h-4 w-4 shrink-0" />
      <span>{message}</span>
    </div>
  );
}
