"use client";

import { useCallback, useEffect, useState, type ReactNode } from "react";

import { FileUploadField } from "@/components/admin/FileUploadField";
import { AdminThumb } from "@/components/admin/AdminThumb";
import { RichTextField } from "@/components/admin/RichTextField";

export interface FieldDef {
  key: string;
  label: string;
  type?: "text" | "textarea" | "richtext" | "number" | "checkbox" | "select" | "image" | "file";
  options?: { value: string; label: string }[];
  required?: boolean;
  placeholder?: string;
  defaultValue?: string | number | boolean;
}

export interface ColumnDef {
  key: string;
  label: string;
  type?: "text" | "image";
  render?: (row: Record<string, unknown>) => ReactNode;
}

export interface ResourceConfig {
  title: string;
  description?: string;
  basePath: string; // e.g. "categories"
  idKey?: string; // default "id"
  listKey?: string; // wrap key, e.g. "items"; omit if response is a bare array
  listQuery?: string; // extra query string appended to the list fetch, e.g. "includeInactive=true"
  columns: ColumnDef[];
  fields?: FieldDef[];
  canCreate?: boolean;
  canEdit?: boolean;
  canDelete?: boolean;
  rowActions?: (row: Record<string, unknown>, reload: () => void) => ReactNode;
}

const card = "rounded-xl border border-[#1e2235] bg-[#0f1120]";
const btn = "rounded-lg bg-indigo-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-indigo-500 disabled:opacity-50";
const btnGhost = "rounded-lg border border-[#262b40] px-3 py-1.5 text-xs text-gray-300 hover:bg-[#161a2e]";
const inputCls = "w-full rounded-lg border border-[#262b40] bg-[#0c0e1a] px-3 py-2 text-sm text-gray-100 outline-none focus:border-indigo-500";

const PAGE_SIZE = 25;

/** URL-safe slug; keeps unicode letters (incl. Persian) + digits, spaces → "-". */
export function slugify(s: string): string {
  return s
    .trim()
    .toLowerCase()
    .replace(/\s+/g, "-")
    .replace(/[^\p{L}\p{N}-]+/gu, "")
    .replace(/-+/g, "-")
    .replace(/^-|-$/g, "");
}

export function AdminResource({ config }: { config: ResourceConfig }) {
  const idKey = config.idKey ?? "id";
  const [rows, setRows] = useState<Record<string, unknown>[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [editing, setEditing] = useState<Record<string, unknown> | null>(null);
  const [creating, setCreating] = useState(false);
  const [form, setForm] = useState<Record<string, unknown>>({});
  const [query, setQuery] = useState("");
  const [page, setPage] = useState(1);
  const [slugTouched, setSlugTouched] = useState(false);
  const [saving, setSaving] = useState(false);

  const url = (suffix = "") => `/api/admin/resource/${config.basePath}${suffix}`;

  const reload = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await fetch(url(config.listQuery ? `?${config.listQuery}` : ""), { cache: "no-store" });
      const data = await res.json();
      if (!res.ok) throw new Error(data?.error ?? "Failed to load");
      const list = config.listKey ? data?.[config.listKey] : data;
      setRows(Array.isArray(list) ? list : (data?.items ?? []));
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load");
    } finally {
      setLoading(false);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [config.basePath, config.listKey, config.listQuery]);

  useEffect(() => {
    reload();
  }, [reload]);

  const hasSlug = !!config.fields?.some((f) => f.key === "slug");

  // Update a field; auto-fill slug from name until the slug is edited by hand.
  const setField = (key: string, value: unknown) => {
    setForm((prev) => {
      const next = { ...prev, [key]: value };
      if (key === "name" && hasSlug && !slugTouched) next.slug = slugify(String(value ?? ""));
      return next;
    });
    if (key === "slug") setSlugTouched(true);
  };

  const openCreate = () => {
    const init: Record<string, unknown> = {};
    config.fields?.forEach((f) => (init[f.key] = f.defaultValue ?? (f.type === "checkbox" ? false : "")));
    setForm(init);
    setSlugTouched(false); // new record → keep syncing slug from name
    setCreating(true);
    setEditing(null);
  };

  const openEdit = (row: Record<string, unknown>) => {
    const init: Record<string, unknown> = {};
    config.fields?.forEach((f) => (init[f.key] = row[f.key] ?? (f.type === "checkbox" ? false : "")));
    setForm(init);
    setSlugTouched(true); // existing record → never auto-rewrite its slug
    setEditing(row);
    setCreating(false);
  };

  const closeForm = () => {
    setCreating(false);
    setEditing(null);
    setForm({});
  };

  const submit = async () => {
    setSaving(true);
    setError(null);
    try {
      const isEdit = !!editing;
      const res = await fetch(isEdit ? url(`/${editing![idKey]}`) : url(), {
        method: isEdit ? "PUT" : "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(form),
      });
      const data = await res.json().catch(() => null);
      if (!res.ok) throw new Error(data?.error ?? "Save failed");
      closeForm();
      reload();
    } catch (e) {
      setError(e instanceof Error ? e.message : "Save failed");
    } finally {
      setSaving(false);
    }
  };

  const remove = async (row: Record<string, unknown>) => {
    if (!confirm("حذف این مورد؟")) return;
    const res = await fetch(url(`/${row[idKey]}`), { method: "DELETE" });
    if (res.ok) reload();
    else {
      const d = await res.json().catch(() => null);
      setError(d?.error ?? "Delete failed");
    }
  };

  // Client-side search (across all fields) + pagination.
  const q = query.trim().toLowerCase();
  const filtered = q ? rows.filter((r) => JSON.stringify(r).toLowerCase().includes(q)) : rows;
  const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
  const safePage = Math.min(page, totalPages);
  const paged = filtered.slice((safePage - 1) * PAGE_SIZE, safePage * PAGE_SIZE);

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold text-white">{config.title}</h1>
          {config.description && <p className="mt-1 text-sm text-gray-400">{config.description}</p>}
        </div>
        <div className="flex items-center gap-2">
          <input
            className="w-52 rounded-lg border border-[#262b40] bg-[#0c0e1a] px-3 py-2 text-sm text-gray-100 outline-none focus:border-indigo-500"
            placeholder="جستجو…" value={query}
            onChange={(e) => { setQuery(e.target.value); setPage(1); }}
          />
          {config.canCreate && config.fields && (
            <button className={btn} onClick={openCreate}>+ مورد جدید</button>
          )}
        </div>
      </div>

      {error && <p className="rounded-lg bg-red-500/10 px-3 py-2 text-sm text-red-300">{error}</p>}

      <div className={`${card} overflow-hidden`}>
        <table className="w-full text-sm">
          <thead>
            <tr className="border-b border-[#1e2235] text-start text-xs text-gray-500">
              {config.columns.map((c) => (
                <th key={c.key} className="px-4 py-3 font-medium">{c.label}</th>
              ))}
              {(config.canEdit || config.canDelete || config.rowActions) && (
                <th className="px-4 py-3 text-end font-medium">عملیات</th>
              )}
            </tr>
          </thead>
          <tbody>
            {loading ? (
              <tr><td className="px-4 py-8 text-center text-gray-500" colSpan={99}>در حال بارگذاری…</td></tr>
            ) : paged.length === 0 ? (
              <tr><td className="px-4 py-8 text-center text-gray-500" colSpan={99}>رکوردی یافت نشد.</td></tr>
            ) : (
              paged.map((row, i) => (
                <tr key={String(row[idKey] ?? i)} className="border-b border-[#161a2e] hover:bg-[#12152a]">
                  {config.columns.map((c) => (
                    <td key={c.key} className="px-4 py-3 text-gray-200">
                      {c.render ? c.render(row) : c.type === "image" ? <AdminThumb src={row[c.key]} /> : formatCell(row[c.key])}
                    </td>
                  ))}
                  {(config.canEdit || config.canDelete || config.rowActions) && (
                    <td className="px-4 py-3">
                      <div className="flex items-center justify-end gap-2">
                        {config.rowActions?.(row, reload)}
                        {config.canEdit && config.fields && (
                          <button className={btnGhost} onClick={() => openEdit(row)}>ویرایش</button>
                        )}
                        {config.canDelete && (
                          <button
                            className="rounded-lg border border-red-500/30 px-3 py-1.5 text-xs text-red-300 hover:bg-red-500/10"
                            onClick={() => remove(row)}
                          >
                            حذف
                          </button>
                        )}
                      </div>
                    </td>
                  )}
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>

      {!loading && filtered.length > 0 && (
        <div className="flex items-center justify-between text-xs text-gray-500" dir="rtl">
          <span>{filtered.length.toLocaleString("fa-IR")} مورد{q ? " (فیلترشده)" : ""}</span>
          {totalPages > 1 && (
            <div className="flex items-center gap-2">
              <button className={btnGhost} disabled={safePage <= 1} onClick={() => setPage((p) => Math.max(1, p - 1))}>قبلی</button>
              <span>صفحهٔ {safePage.toLocaleString("fa-IR")} از {totalPages.toLocaleString("fa-IR")}</span>
              <button className={btnGhost} disabled={safePage >= totalPages} onClick={() => setPage((p) => Math.min(totalPages, p + 1))}>بعدی</button>
            </div>
          )}
        </div>
      )}

      {(creating || editing) && config.fields && (
        <div className="fixed inset-0 z-50 flex items-stretch justify-center bg-black/70 p-2 sm:p-6" onClick={closeForm}>
          <div className={`${card} flex max-h-full w-full max-w-5xl flex-col`} onClick={(e) => e.stopPropagation()}>
            <div className="flex items-center justify-between border-b border-[#1e2235] px-5 py-3">
              <h2 className="text-sm font-semibold text-white">
                {editing ? "ویرایش" : "افزودن"} — {config.title}
              </h2>
              <button className="rounded-lg px-2 py-1 text-gray-400 hover:bg-[#161a2e] hover:text-white" onClick={closeForm}>✕</button>
            </div>
            <div className="grid flex-1 grid-cols-1 gap-4 overflow-y-auto p-5 sm:grid-cols-2">
              {config.fields.map((f) => (
                <div key={f.key} className={f.type === "textarea" || f.type === "richtext" ? "sm:col-span-2" : ""}>
                  {f.type !== "checkbox" && (
                    <label className="mb-1 block text-xs font-medium text-gray-400">
                      {f.label}{f.required && <span className="text-red-400"> *</span>}
                    </label>
                  )}
                  {f.type === "richtext" ? (
                    <RichTextField value={String(form[f.key] ?? "")} onChange={(html) => setForm({ ...form, [f.key]: html })} />
                  ) : f.type === "textarea" ? (
                    <textarea className={`${inputCls} min-h-[160px]`} placeholder={f.placeholder}
                      value={String(form[f.key] ?? "")} onChange={(e) => setForm({ ...form, [f.key]: e.target.value })} />
                  ) : f.type === "select" ? (
                    <select className={inputCls} value={String(form[f.key] ?? "")}
                      onChange={(e) => setForm({ ...form, [f.key]: e.target.value })}>
                      <option value="">—</option>
                      {f.options?.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
                    </select>
                  ) : f.type === "checkbox" ? (
                    <label className="flex items-center gap-2 text-sm text-gray-300">
                      <input type="checkbox" checked={!!form[f.key]} onChange={(e) => setForm({ ...form, [f.key]: e.target.checked })} />
                      {f.label}
                    </label>
                  ) : f.type === "image" || f.type === "file" ? (
                    <FileUploadField
                      value={String(form[f.key] ?? "")}
                      onChange={(url) => setForm({ ...form, [f.key]: url })}
                      accept={f.type === "image" ? "image/*" : "*/*"}
                    />
                  ) : (
                    <input type={f.type === "number" ? "number" : "text"} className={inputCls} placeholder={f.placeholder}
                      value={String(form[f.key] ?? "")}
                      onChange={(e) => setField(f.key, f.type === "number" ? Number(e.target.value) : e.target.value)} />
                  )}
                </div>
              ))}
            </div>
            <div className="flex items-center justify-end gap-2 border-t border-[#1e2235] px-5 py-3">
              <button className={btnGhost} onClick={closeForm}>انصراف</button>
              <button className={btn} onClick={submit} disabled={saving}>{saving ? "در حال ذخیره…" : "ذخیره"}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function formatCell(v: unknown): ReactNode {
  if (v === null || v === undefined || v === "") return <span className="text-gray-600">—</span>;
  if (typeof v === "boolean") return v ? "✓" : "✗";
  if (Array.isArray(v)) return v.join(", ");
  if (typeof v === "object") return JSON.stringify(v).slice(0, 40);
  const s = String(v);
  return s.length > 60 ? s.slice(0, 60) + "…" : s;
}
