"use client";

import { useState } from "react";

/** A single editable field in a child row. */
export type FieldDef = {
  key: string;
  label: string;
  type?: "text" | "number" | "date" | "checkbox" | "select";
  options?: { value: string; label: string }[];
  width?: number;
  /** Numeric granularity. Defaults to money (0.01); a tax rate stored as a
   *  fraction needs finer, or the browser rejects 0.0825 as off-step. */
  step?: string;
};

export type ChildConfig = {
  /** URL segment: installments | vehicles | drivers | beneficiaries | claims */
  apiKind: string;
  title: string;
  fields: FieldDef[];
};

type RowValues = Record<string, string | boolean>;

function toDateInput(v: unknown): string {
  if (!v || typeof v !== "string") return "";
  const d = new Date(v);
  return isNaN(d.getTime()) ? "" : d.toISOString().slice(0, 10);
}

/** Build editable values for a field from an existing row (or blank). */
function rowToValues(fields: FieldDef[], row?: Record<string, unknown>): RowValues {
  const v: RowValues = {};
  for (const f of fields) {
    const raw = row?.[f.key];
    if (f.type === "checkbox") v[f.key] = !!raw;
    else if (f.type === "date") v[f.key] = toDateInput(raw);
    else v[f.key] = raw == null ? "" : String(raw);
  }
  return v;
}

/** Coerce editable values into an API payload (numbers/blanks handled). */
function valuesToPayload(fields: FieldDef[], v: RowValues): Record<string, unknown> {
  const out: Record<string, unknown> = {};
  for (const f of fields) {
    const val = v[f.key];
    if (f.type === "checkbox") out[f.key] = !!val;
    else if (f.type === "number") {
      const s = String(val).trim();
      out[f.key] = s === "" ? undefined : Number(s);
    } else {
      const s = String(val).trim();
      out[f.key] = s === "" ? undefined : s;
    }
  }
  return out;
}

/**
 * Generic add/edit/remove editor for a policy's child collection. The parent
 * owns the API calls (so it can reload the policy afterward); this component is
 * pure UI over `rows` plus add/save/remove callbacks.
 */
export function ChildCollection({
  config,
  rows,
  canEdit,
  onAdd,
  onSave,
  onRemove,
}: {
  config: ChildConfig;
  rows: Record<string, unknown>[];
  canEdit: boolean;
  onAdd: (payload: Record<string, unknown>) => Promise<void>;
  onSave: (id: string, payload: Record<string, unknown>) => Promise<void>;
  onRemove: (id: string) => Promise<void>;
}) {
  const [editingId, setEditingId] = useState<string | null>(null);
  const [adding, setAdding] = useState(false);
  const [values, setValues] = useState<RowValues>({});
  const [busy, setBusy] = useState(false);

  function startAdd() {
    setEditingId(null);
    setAdding(true);
    setValues(rowToValues(config.fields));
  }
  function startEdit(row: Record<string, unknown>) {
    setAdding(false);
    setEditingId(String(row.id));
    setValues(rowToValues(config.fields, row));
  }
  function cancel() {
    setAdding(false);
    setEditingId(null);
  }

  async function submit() {
    setBusy(true);
    try {
      const payload = valuesToPayload(config.fields, values);
      if (editingId) await onSave(editingId, payload);
      else await onAdd(payload);
      cancel();
    } catch (e) {
      window.alert((e as Error)?.message ?? "No se pudo guardar.");
    } finally {
      setBusy(false);
    }
  }

  async function remove(id: string) {
    if (!window.confirm("¿Eliminar este registro?")) return;
    try {
      await onRemove(id);
    } catch (e) {
      window.alert((e as Error)?.message ?? "No se pudo eliminar.");
    }
  }

  const colCount = config.fields.length + (canEdit ? 1 : 0);

  function editorRow() {
    return (
      <tr>
        <td colSpan={colCount}>{editor()}</td>
      </tr>
    );
  }

  function editor() {
    return (
      <div className="child-editor">
        <div className="form-grid">
          {config.fields.map((f) => (
            <label className="field" key={f.key}>
              <span className="field-label">{f.label}</span>
              {f.type === "checkbox" ? (
                <input
                  type="checkbox"
                  checked={!!values[f.key]}
                  onChange={(e) => setValues({ ...values, [f.key]: e.target.checked })}
                />
              ) : f.type === "select" ? (
                <select
                  className="select"
                  value={String(values[f.key] ?? "")}
                  onChange={(e) => setValues({ ...values, [f.key]: e.target.value })}
                >
                  <option value="">—</option>
                  {f.options?.map((o) => (
                    <option key={o.value} value={o.value}>
                      {o.label}
                    </option>
                  ))}
                </select>
              ) : (
                <input
                  className="input"
                  type={f.type === "number" ? "number" : f.type === "date" ? "date" : "text"}
                  step={f.type === "number" ? f.step ?? "0.01" : undefined}
                  value={String(values[f.key] ?? "")}
                  onChange={(e) => setValues({ ...values, [f.key]: e.target.value })}
                />
              )}
            </label>
          ))}
        </div>
        <div className="form-actions">
          <button type="button" className="btn btn-primary" onClick={submit} disabled={busy}>
            {busy ? "Guardando…" : editingId ? "Guardar" : "Agregar"}
          </button>
          <button type="button" className="btn btn-ghost" onClick={cancel}>
            Cancelar
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className="card" style={{ padding: 16, marginBottom: 14 }}>
      <div className="child-head">
        <h3 className="section-title" style={{ margin: 0 }}>
          {config.title}
          <span className="section-count"> {rows.length}</span>
        </h3>
        {canEdit && !adding && editingId === null && (
          <button type="button" className="btn btn-outline" onClick={startAdd}>
            + Agregar
          </button>
        )}
      </div>

      {rows.length === 0 && !adding ? (
        <div className="empty-inline">Sin registros.</div>
      ) : (
        <div className="tx-scroll">
          <table className="tx-table">
            <thead>
              <tr>
                {config.fields.map((f) => (
                  <th key={f.key}>{f.label}</th>
                ))}
                {canEdit && <th className="num">Acciones</th>}
              </tr>
            </thead>
            <tbody>
              {adding && editorRow()}
              {rows.map((row) =>
                editingId === String(row.id) ? (
                  <tr key={String(row.id)}>
                    <td colSpan={colCount}>{editor()}</td>
                  </tr>
                ) : (
                  <tr key={String(row.id)}>
                    {config.fields.map((f) => (
                      <td key={f.key}>{cellText(f, row[f.key])}</td>
                    ))}
                    {canEdit && (
                      <td>
                        <div className="row-actions">
                          <button
                            type="button"
                            className="btn btn-ghost"
                            onClick={() => startEdit(row)}
                          >
                            Editar
                          </button>
                          <button
                            type="button"
                            className="btn btn-ghost"
                            onClick={() => remove(String(row.id))}
                          >
                            Eliminar
                          </button>
                        </div>
                      </td>
                    )}
                  </tr>
                ),
              )}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function cellText(f: FieldDef, raw: unknown): string {
  if (f.type === "checkbox") return raw ? "Sí" : "No";
  if (f.type === "date") return toDateInput(raw) || "—";
  if (f.type === "select") {
    const opt = f.options?.find((o) => o.value === String(raw));
    return opt ? opt.label : "—";
  }
  return raw == null || raw === "" ? "—" : String(raw);
}
