"use client";

import { useState } from "react";
import { Save, Trash2, Plus, Loader2 } from "lucide-react";
import NumberInput from "./NumberInput";
import { toastError, toastSuccess } from "@/lib/toast";

export type Col = {
  key: string;
  label: string;
  type?: "text" | "number" | "bool";
  readonly?: boolean;
};

type Row = Record<string, unknown>;

// سلولِ ورودی — در سطحِ ماژول تعریف شده تا با هر کلید دوباره mount نشود (وگرنه
// اینپوت پس از یک حرف فوکوس را از دست می‌دهد).
function Cell({
  row,
  col,
  onChange,
}: {
  row: Row;
  col: Col;
  onChange: (v: unknown) => void;
}) {
  const v = row[col.key];
  if (col.type === "bool") {
    return (
      <input
        type="checkbox"
        checked={!!v && v !== 0}
        disabled={col.readonly}
        onChange={(e) => onChange(e.target.checked)}
      />
    );
  }
  if (col.type === "number") {
    // ورودیِ عددیِ گروه‌بندی‌شده (جداکننده‌ی هزارگان) و قابلِ تایپ با کیبورد.
    return (
      <NumberInput
        style={{ minWidth: 90 }}
        value={Number(v ?? 0)}
        disabled={col.readonly}
        onChange={onChange}
      />
    );
  }
  return (
    <input
      className="inp"
      style={{ minWidth: 110 }}
      type="text"
      value={v === null || v === undefined ? "" : String(v)}
      readOnly={col.readonly}
      onChange={(e) => onChange(e.target.value)}
    />
  );
}

export default function EditableTable({
  cols,
  rows,
  onSave,
  onDelete,
  newTemplate,
  extra,
  preview,
}: {
  cols: Col[];
  rows: Row[];
  onSave: (row: Row) => Promise<void>;
  onDelete: (id: string) => Promise<void>;
  newTemplate: Row;
  /** ستون/دکمه‌ی اضافی برای هر ردیف (مثلاً آپلود تصویر). */
  extra?: (row: Row) => React.ReactNode;
  /** پیش‌نمایشِ تصویرِ ابتدای ردیف (مثلاً فرش یا کارت). */
  preview?: (row: Row) => React.ReactNode;
}) {
  const [draft, setDraft] = useState<Row>({ ...newTemplate });
  const [busy, setBusy] = useState<string | null>(null);

  // نسخه‌ی محلیِ قابلِ‌ویرایش هر ردیف.
  const [edit, setEdit] = useState<Record<string, Row>>({});
  const rowState = (r: Row) => edit[String(r.id)] ?? r;
  const patch = (id: string, key: string, val: unknown) =>
    setEdit((e) => ({ ...e, [id]: { ...(e[id] ?? rows.find((r) => String(r.id) === id)!), [key]: val } }));

  // پیش از ذخیره، هر ستون را به نوعِ اعلام‌شده تبدیل کن تا سرور عددِ رشته‌ای نگیرد
  // (وگرنه 400: bad request). اعداد → number، بولین‌ها → boolean.
  const coerce = (row: Row): Row => {
    const out: Row = { ...row };
    for (const c of cols) {
      if (c.type === "number") out[c.key] = Number(out[c.key] ?? 0) || 0;
      else if (c.type === "bool") out[c.key] = !!out[c.key] && out[c.key] !== 0;
    }
    return out;
  };

  return (
    <div className="card overflow-x-auto">
      <table>
        <thead>
          <tr>
            {preview && <th>پیش‌نمایش</th>}
            {cols.map((c) => (
              <th key={c.key}>{c.label}</th>
            ))}
            <th></th>
          </tr>
        </thead>
        <tbody>
          {rows.map((r) => {
            const id = String(r.id);
            const rs = rowState(r);
            return (
              <tr key={id}>
                {preview && <td>{preview(r)}</td>}
                {cols.map((c) => (
                  <td key={c.key}>
                    <Cell row={rs} col={c} onChange={(v) => patch(id, c.key, v)} />
                  </td>
                ))}
                <td className="flex items-center gap-1">
                  <button
                    className="btn btn-gold"
                    disabled={busy === id}
                    onClick={async () => {
                      setBusy(id);
                      try {
                        await onSave(coerce(rs));
                        toastSuccess("ذخیره شد");
                      } catch (e) {
                        toastError((e as Error).message);
                      } finally {
                        setBusy(null);
                      }
                    }}
                  >
                    {busy === id ? (
                      <Loader2 size={14} className="animate-spin" />
                    ) : (
                      <Save size={14} />
                    )}
                  </button>
                  <button className="btn btn-danger" onClick={() => onDelete(id)}>
                    <Trash2 size={14} />
                  </button>
                  {extra?.(r)}
                </td>
              </tr>
            );
          })}
          {/* ردیفِ افزودن */}
          <tr style={{ background: "rgba(233,185,73,.06)" }}>
            {preview && <td />}
            {cols.map((c) => (
              <td key={c.key}>
                <Cell
                  row={draft}
                  col={{ ...c, readonly: false }}
                  onChange={(v) => setDraft((d) => ({ ...d, [c.key]: v }))}
                />
              </td>
            ))}
            <td>
              <button
                className="btn btn-ghost flex items-center gap-1"
                disabled={busy === "__new__"}
                onClick={async () => {
                  setBusy("__new__");
                  try {
                    await onSave(coerce(draft));
                    setDraft({ ...newTemplate });
                    toastSuccess("افزوده شد");
                  } catch (e) {
                    toastError((e as Error).message);
                  } finally {
                    setBusy(null);
                  }
                }}
              >
                {busy === "__new__" ? (
                  <Loader2 size={14} className="animate-spin" />
                ) : (
                  <Plus size={14} />
                )}{" "}
                افزودن
              </button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  );
}
