"use client";

import { useState } from "react";
import { useForm, type FieldValues, type DefaultValues } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import { Plus, Pencil, Trash2, Download } from "lucide-react";
import { z } from "zod";
import {
  Button,
  Dialog,
  Input,
  EmptyState,
  FormField,
  ConfirmDialog,
  Select,
} from "@/components/ds";
import { HospitalityTablePage } from "@/modules/hospitality/design-system";
import { HospitalityPageLoader, HospitalityPageError, exportToCsv } from "@/modules/hospitality/pages/shared";
import { useTenantId } from "@/hooks/useTenantId";
import { useHospitalityCapabilities } from "@/modules/hospitality/hooks/useHospitalityCapabilities";
import { HospitalityStatusChip } from "@/modules/hospitality/design-system";
import { HospitalityBundleGate } from "@/modules/hospitality/components/HospitalityBundleGate";

export type HospitalityFieldConfig = {
  name: string;
  label: string;
  type?: "text" | "number" | "select";
  options?: { value: string; label: string }[];
  required?: boolean;
};

export type HospitalityColumnConfig = {
  key: string;
  header: string;
  type?: "status" | "datetime" | "text";
  render?: (row: Record<string, unknown>) => React.ReactNode;
};

type ApiResource = {
  list: (tenantId: string, params?: { page?: number; page_size?: number }) => Promise<Record<string, unknown>[]>;
  create?: (tenantId: string, body: Record<string, unknown>) => Promise<unknown>;
  update?: (tenantId: string, id: string, body: Record<string, unknown>) => Promise<unknown>;
  remove?: (tenantId: string, id: string) => Promise<unknown>;
};

export type HospitalityListConfig = {
  title: string;
  description?: string;
  breadcrumb?: string;
  resourceKey: string;
  bundleFeature?: string | null;
  permission?: string;
  api: ApiResource;
  columns: HospitalityColumnConfig[];
  createFields?: HospitalityFieldConfig[];
  editFields?: HospitalityFieldConfig[];
  filterDeleted?: boolean;
};

function buildSchema(fields: HospitalityFieldConfig[]) {
  const shape: Record<string, z.ZodTypeAny> = {};
  for (const f of fields) {
    shape[f.name] = f.required
      ? z.string().min(1, `${f.label} الزامی است`)
      : z.string().optional();
  }
  return z.object(shape);
}

function renderCell(col: HospitalityColumnConfig, row: Record<string, unknown>) {
  if (col.render) return col.render(row);
  const val = row[col.key];
  if (col.type === "status" && val) return <HospitalityStatusChip status={String(val)} />;
  if (col.type === "datetime" && val) {
    try {
      return new Date(String(val)).toLocaleString("fa-IR");
    } catch {
      return String(val);
    }
  }
  return val != null ? String(val) : "—";
}

export function createHospitalityListPage(config: HospitalityListConfig) {
  return function HospitalityListPage() {
    const { tenantId } = useTenantId();
    const qc = useQueryClient();
    const caps = useHospitalityCapabilities();
    const [createOpen, setCreateOpen] = useState(false);
    const [editRow, setEditRow] = useState<Record<string, unknown> | null>(null);
    const [deleteId, setDeleteId] = useState<string | null>(null);
    const [page, setPage] = useState(1);
    const pageSize = 20;

    const createFields = config.createFields ?? [];
    const editFields = config.editFields ?? createFields;
    const createSchema = buildSchema(createFields);
    const editSchema = buildSchema(editFields);

    const listQ = useQuery({
      queryKey: ["hospitality", tenantId, config.resourceKey, page],
      queryFn: () => config.api.list(tenantId!, { page, page_size: pageSize }),
      enabled: !!tenantId,
    });

    const createForm = useForm({
      resolver: zodResolver(createSchema),
      defaultValues: Object.fromEntries(createFields.map((f) => [f.name, ""])) as DefaultValues<FieldValues>,
    });
    const editForm = useForm({ resolver: zodResolver(editSchema) });

    const invalidate = () =>
      qc.invalidateQueries({ queryKey: ["hospitality", tenantId, config.resourceKey] });

    const createM = useMutation({
      mutationFn: (d: FieldValues) => config.api.create!(tenantId!, d),
      onSuccess: async () => {
        toast.success("رکورد ایجاد شد");
        setCreateOpen(false);
        createForm.reset();
        await invalidate();
      },
      onError: (e: Error) => toast.error(e.message),
    });

    const updateM = useMutation({
      mutationFn: (d: FieldValues) => config.api.update!(tenantId!, String(editRow!.id), d),
      onSuccess: async () => {
        toast.success("به‌روزرسانی شد");
        setEditRow(null);
        await invalidate();
      },
      onError: (e: Error) => toast.error(e.message),
    });

    const deleteM = useMutation({
      mutationFn: (id: string) => config.api.remove!(tenantId!, id),
      onSuccess: async () => {
        toast.success("حذف شد");
        setDeleteId(null);
        await invalidate();
      },
      onError: (e: Error) => toast.error(e.message),
    });

    if (!tenantId || listQ.isLoading || caps.isLoading) return <HospitalityPageLoader />;
    if (listQ.error) return <HospitalityPageError error={listQ.error} onRetry={() => listQ.refetch()} />;

    let rows = listQ.data ?? [];
    if (config.filterDeleted) rows = rows.filter((r) => !r.is_deleted);

    const tableColumns = [
      ...config.columns.map((c) => ({
        key: c.key,
        header: c.header,
        render: (row: Record<string, unknown>) => renderCell(c, row),
      })),
      {
        key: "actions",
        header: "عملیات",
        searchable: false as const,
        render: (row: Record<string, unknown>) => (
          <div className="flex gap-1">
            {config.api.update ? (
              <Button
                variant="ghost"
                size="icon"
                aria-label="ویرایش"
                onClick={() => {
                  setEditRow(row);
                  editForm.reset(Object.fromEntries(editFields.map((f) => [f.name, row[f.name] ?? ""])));
                }}
              >
                <Pencil className="h-4 w-4" />
              </Button>
            ) : null}
            {config.api.remove ? (
              <Button variant="ghost" size="icon" aria-label="حذف" onClick={() => setDeleteId(String(row.id))}>
                <Trash2 className="h-4 w-4" />
              </Button>
            ) : null}
          </div>
        ),
      },
    ];

    const body = (
      <HospitalityTablePage
        title={config.title}
        description={config.description}
        breadcrumb={config.breadcrumb ?? config.title}
        columns={tableColumns}
        rows={rows}
        actions={
          config.api.create ? (
            <Button onClick={() => setCreateOpen(true)}>
              <Plus className="h-4 w-4" />
              جدید
            </Button>
          ) : undefined
        }
        toolbar={
          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => exportToCsv(config.title, rows, config.columns.map((c) => c.key))}
            >
              <Download className="h-4 w-4" />
              خروجی
            </Button>
            <Button variant="outline" size="sm" disabled={page <= 1} onClick={() => setPage((p) => p - 1)}>
              قبلی
            </Button>
            <span className="text-xs text-[var(--muted)]">صفحه {page}</span>
            <Button
              variant="outline"
              size="sm"
              disabled={rows.length < pageSize}
              onClick={() => setPage((p) => p + 1)}
            >
              بعدی
            </Button>
          </div>
        }
        empty={
          <EmptyState
            title="موردی یافت نشد"
            action={
              config.api.create ? (
                <Button onClick={() => setCreateOpen(true)}>ایجاد اولین رکورد</Button>
              ) : undefined
            }
          />
        }
      />
    );

    const pageContent = config.bundleFeature ? (
      <HospitalityBundleGate feature={config.bundleFeature} capabilities={caps.data}>
        {body}
      </HospitalityBundleGate>
    ) : (
      body
    );

    return (
      <>
        {pageContent}
        {config.api.create && createFields.length > 0 ? (
          <Dialog open={createOpen} onClose={() => setCreateOpen(false)} title={`${config.title} — جدید`}>
            <form className="space-y-3" onSubmit={createForm.handleSubmit((d) => createM.mutate(d))}>
              {createFields.map((f) => (
                <FormField key={f.name} label={f.label}>
                  {f.type === "select" && f.options ? (
                    <Select {...createForm.register(f.name)}>
                      {f.options.map((o) => (
                        <option key={o.value} value={o.value}>
                          {o.label}
                        </option>
                      ))}
                    </Select>
                  ) : (
                    <Input type={f.type ?? "text"} {...createForm.register(f.name)} />
                  )}
                </FormField>
              ))}
              <div className="flex justify-end gap-2">
                <Button type="button" variant="outline" onClick={() => setCreateOpen(false)}>
                  انصراف
                </Button>
                <Button type="submit" disabled={createM.isPending}>
                  ذخیره
                </Button>
              </div>
            </form>
          </Dialog>
        ) : null}
        {editRow && config.api.update ? (
          <Dialog open={!!editRow} onClose={() => setEditRow(null)} title={`${config.title} — ویرایش`}>
            <form className="space-y-3" onSubmit={editForm.handleSubmit((d) => updateM.mutate(d))}>
              {editFields.map((f) => (
                <FormField key={f.name} label={f.label}>
                  <Input {...editForm.register(f.name)} />
                </FormField>
              ))}
              <div className="flex justify-end gap-2">
                <Button type="button" variant="outline" onClick={() => setEditRow(null)}>
                  انصراف
                </Button>
                <Button type="submit" disabled={updateM.isPending}>
                  ذخیره
                </Button>
              </div>
            </form>
          </Dialog>
        ) : null}
        <ConfirmDialog
          open={!!deleteId}
          onClose={() => setDeleteId(null)}
          onConfirm={() => deleteId && deleteM.mutate(deleteId)}
          title="حذف رکورد"
          description="آیا از حذف این رکورد مطمئن هستید؟"
          confirmLabel="حذف"
          danger
        />
      </>
    );
  };
}
