import React, { useEffect, useMemo, useState } from "react";
import PageHeader from "../common/PageHeader.jsx";
import DataTable from "../common/DataTable.jsx";
import ErrorBanner from "../common/ErrorBanner.jsx";
import EntityModal from "../common/EntityModal.jsx";
import ConfirmDialog from "../common/ConfirmDialog.jsx";

function coerceValue(type, value) {
  if (value === "" || value == null) return null;
  if (type === "number") {
    const n = Number(value);
    return Number.isFinite(n) ? n : null;
  }
  if (type === "checkbox") return value ? 1 : 0;
  return value;
}

function buildPayload(fields, draft) {
  const payload = {};
  for (const field of fields) {
    if (field.readOnly) continue;
    const raw = draft[field.key];
    if (field.type === "checkbox") {
      payload[field.key] = raw ? 1 : 0;
      continue;
    }
    if (raw == null || String(raw).trim() === "") continue;
    payload[field.key] = coerceValue(field.type, raw);
  }
  return payload;
}

function toInitialDraft(fields, source = {}) {
  return fields.reduce((acc, field) => {
    const value = source[field.key];
    if (field.type === "checkbox") {
      acc[field.key] = Boolean(value);
    } else {
      acc[field.key] = value ?? "";
    }
    return acc;
  }, {});
}

function FieldInput({ field, value, onChange, options = [] }) {
  if (field.type === "select") {
    return (
      <select className="swi-input" value={value ?? ""} onChange={(e) => onChange(e.target.value)}>
        <option value="">Select {field.label}</option>
        {options.map((opt) => (
          <option key={opt.value} value={opt.value}>{opt.label}</option>
        ))}
      </select>
    );
  }
  if (field.type === "textarea") {
    return (
      <textarea
        className="swi-input"
        rows={4}
        value={value ?? ""}
        onChange={(e) => onChange(e.target.value)}
        placeholder={field.placeholder || `Enter ${field.label}`}
      />
    );
  }
  if (field.type === "checkbox") {
    return (
      <label className="swi-check">
        <input type="checkbox" checked={Boolean(value)} onChange={(e) => onChange(e.target.checked)} />
        <span>{field.checkboxLabel || field.label}</span>
      </label>
    );
  }
  return (
    <input
      className="swi-input"
      type={field.type === "number" ? "number" : "text"}
      value={value ?? ""}
      onChange={(e) => onChange(e.target.value)}
      placeholder={field.placeholder || `Enter ${field.label}`}
    />
  );
}

export default function EntityCrudPage({
  title,
  subtitle,
  keyField = "id",
  fields = [],
  columns = [],
  listFn,
  createFn,
  updateFn,
  deleteFn,
  onAfterLoad,
  extraPanel
}) {
  const [rows, setRows] = useState([]);
  const [selected, setSelected] = useState(null);
  const [error, setError] = useState("");
  const [saving, setSaving] = useState(false);
  const [createOpen, setCreateOpen] = useState(false);
  const [editOpen, setEditOpen] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);
  const [createDraft, setCreateDraft] = useState(() => toInitialDraft(fields));
  const [editDraft, setEditDraft] = useState(() => toInitialDraft(fields));

  const fieldOptions = useMemo(() => {
    const out = {};
    for (const field of fields) {
      out[field.key] = typeof field.options === "function" ? field.options() : (field.options || []);
    }
    return out;
  }, [fields, rows]);

  async function load() {
    try {
      setError("");
      const data = await listFn();
      setRows(data);
      if (onAfterLoad) onAfterLoad(data);
    } catch (err) {
      setError(err?.response?.data?.message || err.message);
    }
  }

  useEffect(() => {
    load();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    if (!selected) return;
    setEditDraft(toInitialDraft(fields, selected));
  }, [selected, fields]);

  async function handleCreate() {
    setSaving(true);
    try {
      await createFn(buildPayload(fields, createDraft));
      setCreateOpen(false);
      setCreateDraft(toInitialDraft(fields));
      await load();
    } catch (err) {
      setError(err?.response?.data?.message || err.message);
    } finally {
      setSaving(false);
    }
  }

  async function handleUpdate() {
    if (!selected) return;
    setSaving(true);
    try {
      await updateFn(selected[keyField], buildPayload(fields, editDraft));
      setEditOpen(false);
      await load();
    } catch (err) {
      setError(err?.response?.data?.message || err.message);
    } finally {
      setSaving(false);
    }
  }

  async function handleDelete() {
    if (!selected) return;
    setSaving(true);
    try {
      await deleteFn(selected[keyField]);
      setSelected(null);
      setDeleteOpen(false);
      await load();
    } catch (err) {
      setError(err?.response?.data?.message || err.message);
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="portal-page">
      <PageHeader
        title={title}
        subtitle={subtitle}
        actions={(
          <>
            <button type="button" className="swi-btn" onClick={() => setCreateOpen(true)}>Create</button>
            <button type="button" className="swi-btn" onClick={() => selected && setEditOpen(true)} disabled={!selected}>Update</button>
            <button type="button" className="swi-btn swi-btn--danger" onClick={() => selected && setDeleteOpen(true)} disabled={!selected}>Delete</button>
            <button type="button" className="swi-btn swi-btn--ghost" onClick={load}>Refresh</button>
          </>
        )}
      />
      <ErrorBanner message={error} />

      <div className="ptw-panel">
        {selected ? (
          <p className="ptw-muted">
            Selected {keyField}: <strong>{selected[keyField]}</strong>
          </p>
        ) : (
          <p className="ptw-muted">Select a row to update or delete.</p>
        )}
        <DataTable columns={columns} rows={rows} keyField={keyField} onRowClick={setSelected} />
      </div>

      {extraPanel}

      <EntityModal open={createOpen} title={`Create ${title}`} onClose={() => setCreateOpen(false)}>
        <div className="ptw-form-grid-2">
          {fields.map((field) => (
            <label className="swi-field" key={`create-${field.key}`}>
              <span className="swi-field__label">{field.label}</span>
              <FieldInput
                field={field}
                value={createDraft[field.key]}
                options={fieldOptions[field.key]}
                onChange={(value) => setCreateDraft((prev) => ({ ...prev, [field.key]: value }))}
              />
            </label>
          ))}
        </div>
        <div className="ptw-row-actions" style={{ marginTop: "1rem" }}>
          <button type="button" className="swi-btn" onClick={handleCreate} disabled={saving}>Save</button>
        </div>
      </EntityModal>

      <EntityModal open={editOpen} title={`Update ${title}`} onClose={() => setEditOpen(false)}>
        <div className="ptw-form-grid-2">
          {fields.map((field) => (
            <label className="swi-field" key={`edit-${field.key}`}>
              <span className="swi-field__label">{field.label}</span>
              <FieldInput
                field={field}
                value={editDraft[field.key]}
                options={fieldOptions[field.key]}
                onChange={(value) => setEditDraft((prev) => ({ ...prev, [field.key]: value }))}
              />
            </label>
          ))}
        </div>
        <div className="ptw-row-actions" style={{ marginTop: "1rem" }}>
          <button type="button" className="swi-btn" onClick={handleUpdate} disabled={saving}>Save Changes</button>
        </div>
      </EntityModal>

      <ConfirmDialog
        open={deleteOpen}
        title="Delete record?"
        message={`Delete selected ${title} record?`}
        onCancel={() => setDeleteOpen(false)}
        onConfirm={handleDelete}
      />
    </div>
  );
}
