"use client";

import { FormEvent, useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { AdminPageHeader, Banner, Button, EmptyState, Modal } from "@/components/admin/controls";
import { useMe } from "@/hooks/useMe";
import type { CommercialAdminResourceDef } from "../admin/resources";
import {
  createAdminRegistryItem,
  deleteAdminRegistryItem,
  listAdminRegistry,
  type RegistryRecord,
  updateAdminRegistryItem,
} from "../adapters/admin";
import type { AdapterResult } from "../types";
import {
  enumLabel,
  fieldLabel,
  friendlyMessage,
  humanizeCommercialCode,
  isTechnicalField,
} from "../presentation";

const PAGE_SIZE = 10;
const FIELD_GROUPS = [
  { title: "اطلاعات پایه", keys: ["display_name", "title", "description", "category"] },
  { title: "اطلاعات تجاری", keys: ["role", "pricing_model", "amount_minor", "currency", "interval", "trial_days", "duration_days", "grace_period_days"] },
  { title: "قیمت‌گذاری", keys: ["pricing_refs", "tax_class_code", "discount_refs", "coupon_code"] },
  { title: "قابلیت‌ها", keys: ["product_codes", "capability_codes", "feature_refs", "required_capabilities"] },
  { title: "نمایش", keys: ["visibility", "display_order", "trial_eligible"] },
  { title: "انتشار", keys: ["status", "published_at", "starts_at", "ends_at"] },
  { title: "اطلاعات تکمیلی", keys: ["metadata", "attributes", "parameters", "usage_limits", "feature_limits"] },
] as const;

function recordLabel(item: RegistryRecord, resource: CommercialAdminResourceDef): string {
  const name = item[resource.nameField];
  return humanizeCommercialCode(item[resource.codeField], typeof name === "string" ? name : null);
}

function recordCode(item: RegistryRecord, resource: CommercialAdminResourceDef): string {
  const code = item[resource.codeField];
  return code == null ? "" : String(code);
}

function recordTargetId(item: RegistryRecord, resource: CommercialAdminResourceDef): string {
  const target = item.registry_object_id ?? item.id ?? item[resource.codeField];
  return target == null ? "" : String(target);
}

function defaultRecord(resource: CommercialAdminResourceDef): RegistryRecord {
  const seed: RegistryRecord = {
    [resource.codeField]: "",
    [resource.nameField]: "",
    status: "draft",
  };
  if (resource.key === "products") Object.assign(seed, { visibility: "public", display_order: 0 });
  if (resource.key === "trial-rules") Object.assign(seed, { duration_days: 14, grace_period_days: 3, auto_disable: true });
  if (resource.key === "pricing") Object.assign(seed, { pricing_model: "monthly", currency: "IRR", amount_minor: 0 });
  if (resource.key === "policies") Object.assign(seed, { effect: "deny", parameters: { custom_domain_allowed: false, subdomain_only: true, ssl_ready: false } });
  return seed;
}

function parseFieldValue(key: string, input: string, current: unknown): unknown {
  if (Array.isArray(current) || /(_refs|_codes|capabilities)$/.test(key)) {
    return input.split("،").flatMap((part) => part.split(",")).map((part) => part.trim()).filter(Boolean);
  }
  if (typeof current === "number" || /(amount|days|order|percent|limit)$/.test(key)) {
    return input === "" ? null : Number(input);
  }
  return input;
}

function FieldInput({
  name,
  value,
  onChange,
}: {
  name: string;
  value: unknown;
  onChange: (value: unknown) => void;
}) {
  if (Array.isArray(value)) {
    return (
      <div className="sm:col-span-2">
        <p className="text-sm font-medium text-secondary">{fieldLabel(name)}</p>
        <div className="mt-2 flex flex-wrap gap-2">
          {value.length ? value.map((item, index) => (
            <span key={`${String(item)}-${index}`} className="rounded-full bg-sky-50 px-3 py-1 text-xs text-sky-800">
              {humanizeCommercialCode(item)}
            </span>
          )) : <span className="text-xs text-gray-500">موردی انتخاب نشده است.</span>}
        </div>
      </div>
    );
  }
  if (typeof value === "boolean") {
    return (
      <label className="flex cursor-pointer items-center justify-between rounded-xl border border-gray-200 px-4 py-3">
        <span className="text-sm font-medium text-secondary">{fieldLabel(name)}</span>
        <input type="checkbox" checked={value} onChange={(event) => onChange(event.target.checked)} className="h-4 w-4 accent-primary" />
      </label>
    );
  }
  if (value && typeof value === "object" && !Array.isArray(value)) {
    return (
      <fieldset className="rounded-2xl border border-gray-200 p-4">
        <legend className="px-2 text-sm font-semibold text-secondary">{fieldLabel(name)}</legend>
        <div className="grid gap-4 sm:grid-cols-2">
          {Object.entries(value as Record<string, unknown>)
            .filter(([key]) => !isTechnicalField(key))
            .map(([key, nested]) => (
              <FieldInput
                key={key}
                name={key}
                value={nested}
                onChange={(next) => onChange({ ...(value as Record<string, unknown>), [key]: next })}
              />
            ))}
        </div>
      </fieldset>
    );
  }
  const displayValue = value == null ? "" : String(value);
  const selectOptions: Record<string, string[]> = {
    status: ["draft", "active", "published", "inactive"],
    visibility: ["public", "private", "hidden"],
    pricing_model: ["monthly", "yearly", "trial", "enterprise_quote"],
    interval: ["monthly", "yearly"],
    currency: ["IRR"],
  };
  if (selectOptions[name]) {
    return (
      <label className="block">
        <span className="text-sm font-medium text-secondary">{fieldLabel(name)}</span>
        <select value={displayValue} onChange={(event) => onChange(event.target.value)} className="mt-1 w-full rounded-xl border border-gray-200 bg-white px-3 py-2.5 text-sm">
          {selectOptions[name].map((option) => <option key={option} value={option}>{enumLabel(option)}</option>)}
        </select>
      </label>
    );
  }
  return (
    <label className={name === "description" ? "block sm:col-span-2" : "block"}>
      <span className="text-sm font-medium text-secondary">{fieldLabel(name)}</span>
      {name === "description" ? (
        <textarea value={displayValue} onChange={(event) => onChange(event.target.value)} rows={3} className="mt-1 w-full rounded-xl border border-gray-200 px-3 py-2.5 text-sm" />
      ) : (
        <input
          type={typeof value === "number" ? "number" : /(_at|date)$/.test(name) ? "date" : "text"}
          value={displayValue}
          onChange={(event) => onChange(parseFieldValue(name, event.target.value, value))}
          placeholder={Array.isArray(value) ? "موارد را با ویرگول جدا کنید" : undefined}
          className="mt-1 w-full rounded-xl border border-gray-200 px-3 py-2.5 text-sm"
        />
      )}
    </label>
  );
}

function CommercialRecordForm({
  value,
  resource,
  onChange,
}: {
  value: RegistryRecord;
  resource: CommercialAdminResourceDef;
  onChange: (record: RegistryRecord) => void;
}) {
  const visibleKeys = Object.keys(value).filter((key) => !isTechnicalField(key));
  const grouped = new Set<string>(FIELD_GROUPS.flatMap((group) => [...group.keys]));
  const advanced = visibleKeys.filter((key) => !grouped.has(key) && key !== resource.nameField);
  const setField = (key: string, next: unknown) => onChange({ ...value, [key]: next });

  return (
    <div className="max-h-[65vh] space-y-6 overflow-y-auto px-1">
      {FIELD_GROUPS.map((group) => {
        const keys = Array.from(new Set([
          ...(group.title === "اطلاعات پایه" ? [resource.nameField] : []),
          ...group.keys,
        ])).filter((key) => key in value && !isTechnicalField(key));
        if (!keys.length) return null;
        return (
          <section key={group.title} className="rounded-2xl bg-gray-50 p-4">
            <h3 className="mb-4 text-sm font-bold text-secondary">{group.title}</h3>
            <div className="grid gap-4 sm:grid-cols-2">
              {keys.map((key) => <FieldInput key={key} name={key} value={value[key]} onChange={(next) => setField(key, next)} />)}
            </div>
          </section>
        );
      })}
      {advanced.length ? (
        <details className="rounded-2xl border border-gray-200 p-4">
          <summary className="cursor-pointer text-sm font-bold text-secondary">تنظیمات پیشرفته</summary>
          <p className="mt-2 text-xs text-gray-500">این بخش برای تنظیمات کم‌استفاده است. تغییر آن‌ها ممکن است روی انتشار اثر بگذارد.</p>
          <div className="mt-4 grid gap-4 sm:grid-cols-2">
            {advanced.map((key) => <FieldInput key={key} name={key} value={value[key]} onChange={(next) => setField(key, next)} />)}
          </div>
        </details>
      ) : null}
    </div>
  );
}

export function AdminRegistryManager({ resource }: { resource: CommercialAdminResourceDef }) {
  const { me } = useMe();
  const [result, setResult] = useState<AdapterResult<RegistryRecord[]> | null>(null);
  const [error, setError] = useState("");
  const [msg, setMsg] = useState("");
  const [loading, setLoading] = useState(true);
  const [createOpen, setCreateOpen] = useState(false);
  const [editItem, setEditItem] = useState<RegistryRecord | null>(null);
  const [formBody, setFormBody] = useState<RegistryRecord>({});
  const [busy, setBusy] = useState(false);
  const [query, setQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState("all");
  const [sortAsc, setSortAsc] = useState(true);
  const [page, setPage] = useState(1);
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const load = useCallback(async () => {
    setLoading(true);
    setError("");
    const response = await listAdminRegistry(resource, me?.current_tenant_id);
    setResult(response);
    if (["unavailable", "permission_denied", "error"].includes(response.availability)) {
      setError(friendlyMessage(response.message, "بارگذاری اطلاعات انجام نشد. لطفاً دوباره تلاش کنید."));
    }
    setLoading(false);
  }, [me?.current_tenant_id, resource]);

  useEffect(() => { void load(); }, [load]);

  const items = useMemo(() => result?.data ?? [], [result]);
  const filtered = useMemo(() => {
    const normalized = query.trim().toLocaleLowerCase("fa");
    return items
      .filter((item) => statusFilter === "all" || item.status === statusFilter)
      .filter((item) => !normalized || recordLabel(item, resource).toLocaleLowerCase("fa").includes(normalized))
      .sort((a, b) => recordLabel(a, resource).localeCompare(recordLabel(b, resource), "fa") * (sortAsc ? 1 : -1));
  }, [items, query, resource, sortAsc, statusFilter]);
  const pages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
  const visible = filtered.slice((Math.min(page, pages) - 1) * PAGE_SIZE, Math.min(page, pages) * PAGE_SIZE);

  const openCreate = () => {
    setFormBody(defaultRecord(resource));
    setCreateOpen(true);
    setMsg("");
    setError("");
  };
  const openEdit = (item: RegistryRecord) => {
    setEditItem(item);
    setFormBody({ ...item });
    setMsg("");
    setError("");
  };

  const submitCreate = async (event: FormEvent) => {
    event.preventDefault();
    setBusy(true);
    setError("");
    const body = { ...formBody };
    if (!body[resource.codeField]) {
      body[resource.codeField] = `${resource.key.replace(/s$/, "")}.${Date.now().toString(36)}`;
    }
    const response = await createAdminRegistryItem(resource, body);
    if (!response.ok) setError(friendlyMessage(response.message, "ثبت اطلاعات انجام نشد. لطفاً فیلدهای ضروری را بررسی کنید."));
    else {
      setCreateOpen(false);
      setMsg("اطلاعات با موفقیت ثبت شد.");
      await load();
    }
    setBusy(false);
  };

  const submitEdit = async (event: FormEvent) => {
    event.preventDefault();
    if (!editItem) return;
    const targetId = recordTargetId(editItem, resource);
    if (!targetId) return setError("شناسه این مورد پیدا نشد. صفحه را تازه‌سازی کنید.");
    const changedFields = Object.fromEntries(
      Object.entries(formBody).filter(
        ([key, value]) =>
          ![
            "registry_object_id",
            "id",
            "kind",
            "slug",
            "stable_code",
            "created_at",
            "updated_at",
            "created_by",
            "updated_by",
            "published_at",
            "archived_at",
            "is_deleted",
            "clone_of_id",
          ].includes(key) && !Object.is(value, editItem[key])
      )
    );
    if (!Object.keys(changedFields).length) {
      setEditItem(null);
      setMsg("تغییری برای ذخیره وجود نداشت.");
      return;
    }
    setBusy(true);
    const response = await updateAdminRegistryItem(resource, targetId, changedFields);
    if (!response.ok) setError(friendlyMessage(response.message, "ذخیره تغییرات انجام نشد. دوباره تلاش کنید."));
    else {
      setEditItem(null);
      setMsg("تغییرات با موفقیت ذخیره شد.");
      await load();
    }
    setBusy(false);
  };

  const removeItems = async (targets: RegistryRecord[]) => {
    if (!targets.length || !window.confirm(`${targets.length.toLocaleString("fa-IR")} مورد حذف شود؟`)) return;
    setBusy(true);
    for (const item of targets) {
      const targetId = recordTargetId(item, resource);
      if (targetId) {
        const response = await deleteAdminRegistryItem(resource, targetId);
        if (!response.ok) {
          setError(friendlyMessage(response.message, "حذف بعضی موارد انجام نشد."));
          break;
        }
      }
    }
    setSelected(new Set());
    await load();
    setBusy(false);
  };

  return (
    <div className="space-y-6">
      <AdminPageHeader
        title={resource.label}
        subtitle={`جست‌وجو، ویرایش، انتشار و مدیریت ${resource.label}`}
        action={<div className="flex flex-wrap gap-2"><Link href="/admin/commercial"><Button variant="outline">بازگشت</Button></Link>{!resource.readOnly ? <Button onClick={openCreate}>افزودن مورد جدید</Button> : null}</div>}
      />
      {error ? <Banner variant="error">{error}</Banner> : null}
      {msg ? <Banner variant="success">{msg}</Banner> : null}

      <div className="flex flex-wrap items-center gap-3 rounded-2xl border border-gray-100 bg-white p-4 shadow-sm">
        <label className="relative min-w-[220px] flex-1">
          <span className="sr-only">جست‌وجو</span>
          <span className="pointer-events-none absolute right-3 top-2.5" aria-hidden="true">⌕</span>
          <input value={query} onChange={(event) => { setQuery(event.target.value); setPage(1); }} placeholder={`جست‌وجو در ${resource.label}`} className="w-full rounded-xl border border-gray-200 py-2.5 pl-4 pr-10 text-sm" />
        </label>
        <select value={statusFilter} onChange={(event) => { setStatusFilter(event.target.value); setPage(1); }} aria-label="فیلتر وضعیت" className="rounded-xl border border-gray-200 bg-white px-3 py-2.5 text-sm">
          <option value="all">همه وضعیت‌ها</option><option value="active">فعال</option><option value="published">منتشرشده</option><option value="draft">پیش‌نویس</option><option value="inactive">غیرفعال</option>
        </select>
        <Button variant="outline" size="sm" onClick={() => setSortAsc((value) => !value)}>مرتب‌سازی {sortAsc ? "الف تا ی" : "ی تا الف"}</Button>
        {selected.size && !resource.readOnly ? <Button variant="outline" size="sm" disabled={busy} onClick={() => void removeItems(items.filter((item) => selected.has(recordCode(item, resource))))}>حذف انتخاب‌شده‌ها</Button> : null}
      </div>

      <section className="overflow-hidden rounded-2xl border border-gray-100 bg-white shadow-sm">
        {loading ? (
          <div className="space-y-3 p-5" aria-label="در حال بارگذاری">{[1, 2, 3].map((i) => <div key={i} className="h-12 animate-pulse rounded-xl bg-gray-100" />)}</div>
        ) : !visible.length ? (
          <EmptyState message={query || statusFilter !== "all" ? "موردی با این جست‌وجو پیدا نشد." : "هنوز موردی ثبت نشده است."} />
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full min-w-[680px] text-sm">
              <thead className="bg-gray-50 text-right"><tr><th className="w-12 px-4 py-3"><span className="sr-only">انتخاب</span></th><th className="px-4 py-3 font-semibold text-secondary">نام</th><th className="px-4 py-3 font-semibold text-secondary">وضعیت</th><th className="px-4 py-3 font-semibold text-secondary">عملیات</th></tr></thead>
              <tbody>
                {visible.map((item, index) => {
                  const code = recordCode(item, resource) || `row-${index}`;
                  const status = typeof item.status === "string" ? item.status : "inactive";
                  return (
                    <tr key={code} className="border-t border-gray-100 hover:bg-gray-50/60">
                      <td className="px-4 py-3"><input type="checkbox" checked={selected.has(code)} aria-label={`انتخاب ${recordLabel(item, resource)}`} onChange={() => setSelected((current) => { const next = new Set(current); next.has(code) ? next.delete(code) : next.add(code); return next; })} /></td>
                      <td className="px-4 py-3 font-medium text-secondary">{recordLabel(item, resource)}</td>
                      <td className="px-4 py-3"><span className={`rounded-full px-2.5 py-1 text-xs ${status === "active" || status === "published" ? "bg-emerald-50 text-emerald-700" : status === "draft" ? "bg-amber-50 text-amber-700" : "bg-gray-100 text-gray-600"}`}>{enumLabel(status)}</span></td>
                      <td className="px-4 py-3">
                        {resource.readOnly ? (
                          <span className="text-xs text-gray-500">نمایش فقط‌خواندنی</span>
                        ) : (
                          <div className="flex gap-2"><Button variant="outline" size="sm" onClick={() => openEdit(item)}><span aria-hidden="true">✎</span> ویرایش</Button><Button variant="outline" size="sm" disabled={busy} onClick={() => void removeItems([item])}><span aria-hidden="true">♲</span> حذف</Button></div>
                        )}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
        {filtered.length > PAGE_SIZE ? (
          <div className="flex items-center justify-between border-t border-gray-100 px-4 py-3 text-xs text-gray-500">
            <Button size="sm" variant="outline" disabled={page <= 1} onClick={() => setPage((value) => value - 1)}>قبلی</Button>
            <span>صفحه {Math.min(page, pages).toLocaleString("fa-IR")} از {pages.toLocaleString("fa-IR")}</span>
            <Button size="sm" variant="outline" disabled={page >= pages} onClick={() => setPage((value) => value + 1)}>بعدی</Button>
          </div>
        ) : null}
      </section>

      <Modal open={createOpen} onClose={() => setCreateOpen(false)} title={`افزودن ${resource.label}`}>
        <form onSubmit={(event) => void submitCreate(event)} className="space-y-5">
          <CommercialRecordForm value={formBody} resource={resource} onChange={setFormBody} />
          <div className="flex justify-end gap-2"><Button type="button" variant="outline" onClick={() => setCreateOpen(false)}>انصراف</Button><Button type="submit" loading={busy}>ثبت و ذخیره</Button></div>
        </form>
      </Modal>
      <Modal open={Boolean(editItem)} onClose={() => setEditItem(null)} title={`ویرایش ${resource.label}`}>
        <form onSubmit={(event) => void submitEdit(event)} className="space-y-5">
          <CommercialRecordForm value={formBody} resource={resource} onChange={setFormBody} />
          <div className="flex justify-end gap-2"><Button type="button" variant="outline" onClick={() => setEditItem(null)}>انصراف</Button><Button type="submit" loading={busy}>ذخیره تغییرات</Button></div>
        </form>
      </Modal>
    </div>
  );
}
