"use client";

import Link from "next/link";
import { useEffect, useState } from "react";
import { AppShell } from "@/components/AppShell";
import { useCan } from "@/lib/abilities";
import {
  createBankAccount,
  createBankInstitution,
  listBankAccounts,
  listBankInstitutions,
  updateBankAccount,
  updateBankInstitution,
} from "@/lib/api";
import { domainLabel } from "@/lib/labels";
import type {
  BankAccount,
  BankInstitution,
  Currency,
  TransactionDomain,
} from "@/lib/types";

/**
 * Chequera accounts admin — docs/RECEIPT_CAPTURE_SPEC.md §3.
 *
 * Two levels: the bank (institution) and the accounts held at it. Opening an
 * account is rare and consequential — its currency is what every movement
 * booked into it is denominated in, and it can't be changed afterwards without
 * silently re-denominating history, so the edit form deliberately has no
 * currency field.
 *
 * Accounts are never deleted: `bank_transactions.bankAccountId` is a required
 * FK, so a used account can't be removed without destroying its register.
 * Closing one (`active: false`) hides it from new captures while leaving the
 * history readable, matching this app's never-hard-delete convention.
 */
const CURRENCIES: Currency[] = ["MXN", "USD"];
const BUSINESS_LINES: TransactionDomain[] = ["UTILITY", "INSURANCE", "TRUST"];

export default function CuentasChequeraPage() {
  return (
    <AppShell>
      <Cuentas />
    </AppShell>
  );
}

function Cuentas() {
  const canEdit = useCan("bank:manage-accounts");
  const [banks, setBanks] = useState<BankInstitution[] | null>(null);
  const [accounts, setAccounts] = useState<BankAccount[] | null>(null);
  const [error, setError] = useState<string | null>(null);

  function reload() {
    Promise.all([listBankInstitutions(), listBankAccounts()])
      .then(([b, a]) => {
        setBanks(b);
        setAccounts(a);
      })
      .catch((e) => setError(e?.message ?? "No se pudieron cargar las cuentas."));
  }
  useEffect(reload, []);

  if (!canEdit) {
    return (
      <>
        <div className="page-head">
          <h1 className="page-title">Cuentas de chequera</h1>
        </div>
        <div className="state-box state-error">
          No tiene permisos para administrar cuentas bancarias.
        </div>
      </>
    );
  }

  return (
    <>
      <div className="page-head">
        <p className="eyebrow">
          <Link href="/banco">Chequera</Link>
        </p>
        <h1 className="page-title">Cuentas de chequera</h1>
        <p className="section-note">
          Cada cuenta es una chequera física y se lleva por separado. La moneda
          se fija al darla de alta porque todos sus movimientos quedan
          registrados en ella; para cambiarla hay que abrir otra cuenta. Las
          cuentas no se eliminan: se cierran, y su historial sigue consultable.
        </p>
      </div>

      {error && <div className="state-box state-error">{error}</div>}

      {!banks || !accounts ? (
        <div className="empty-inline">
          <span className="spinner" aria-label="Cargando" />
        </div>
      ) : (
        <>
          <BanksSection banks={banks} onChanged={reload} />
          <AccountsSection
            banks={banks}
            accounts={accounts}
            onChanged={reload}
          />
        </>
      )}
    </>
  );
}

/* ------------------------------------------------------------------ banks */

function BanksSection({
  banks,
  onChanged,
}: {
  banks: BankInstitution[];
  onChanged: () => void;
}) {
  const [adding, setAdding] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [name, setName] = useState("");
  const [country, setCountry] = useState("");
  const [busy, setBusy] = useState(false);

  function startAdd() {
    setEditingId(null);
    setAdding(true);
    setName("");
    setCountry("");
  }
  function startEdit(b: BankInstitution) {
    setAdding(false);
    setEditingId(b.id);
    setName(b.name);
    setCountry(b.country ?? "");
  }
  function cancel() {
    setAdding(false);
    setEditingId(null);
  }

  async function submit() {
    if (!name.trim()) {
      window.alert("El nombre del banco es obligatorio.");
      return;
    }
    setBusy(true);
    try {
      const payload = { name: name.trim(), country: country.trim() };
      if (editingId) await updateBankInstitution(editingId, payload);
      else await createBankInstitution(payload);
      cancel();
      onChanged();
    } catch (e) {
      window.alert((e as Error)?.message ?? "No se pudo guardar el banco.");
    } finally {
      setBusy(false);
    }
  }

  const editor = (
    <div className="child-editor">
      <div className="form-grid">
        <label className="field">
          <span className="field-label">
            Banco <span aria-hidden>*</span>
          </span>
          <input
            className="input"
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="Ej. Scotiabank"
          />
        </label>
        <label className="field">
          <span className="field-label">País</span>
          <input
            className="input"
            value={country}
            onChange={(e) => setCountry(e.target.value)}
            placeholder="MX / US"
          />
        </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 }}>
          Bancos
          <span className="section-count"> {banks.length}</span>
        </h3>
        {!adding && editingId === null && (
          <button type="button" className="btn btn-outline" onClick={startAdd}>
            + Agregar
          </button>
        )}
      </div>

      {banks.length === 0 && !adding ? (
        <div className="empty-inline">Sin bancos registrados.</div>
      ) : (
        <div className="tx-scroll">
          <table className="tx-table">
            <thead>
              <tr>
                <th>Banco</th>
                <th>País</th>
                <th className="num">Acciones</th>
              </tr>
            </thead>
            <tbody>
              {adding && (
                <tr>
                  <td colSpan={3}>{editor}</td>
                </tr>
              )}
              {banks.map((b) =>
                editingId === b.id ? (
                  <tr key={b.id}>
                    <td colSpan={3}>{editor}</td>
                  </tr>
                ) : (
                  <tr key={b.id}>
                    <td>{b.name}</td>
                    <td>{b.country || "—"}</td>
                    <td>
                      <div className="row-actions">
                        <button
                          type="button"
                          className="btn btn-ghost"
                          onClick={() => startEdit(b)}
                        >
                          Editar
                        </button>
                      </div>
                    </td>
                  </tr>
                ),
              )}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

/* --------------------------------------------------------------- accounts */

function AccountsSection({
  banks,
  accounts,
  onChanged,
}: {
  banks: BankInstitution[];
  accounts: BankAccount[];
  onChanged: () => void;
}) {
  const [adding, setAdding] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [bankId, setBankId] = useState("");
  const [label, setLabel] = useState("");
  const [currency, setCurrency] = useState<Currency>("MXN");
  const [businessLine, setBusinessLine] = useState<string>("");
  const [active, setActive] = useState(true);
  const [busy, setBusy] = useState(false);

  function startAdd() {
    setEditingId(null);
    setAdding(true);
    setBankId(banks[0]?.id ?? "");
    setLabel("");
    setCurrency("MXN");
    setBusinessLine("");
    setActive(true);
  }
  function startEdit(a: BankAccount) {
    setAdding(false);
    setEditingId(a.id);
    setBankId(a.bankId);
    setLabel(a.label);
    setCurrency(a.currency);
    setBusinessLine(a.businessLine ?? "");
    setActive(a.active);
  }
  function cancel() {
    setAdding(false);
    setEditingId(null);
  }

  async function submit() {
    if (!bankId) {
      window.alert("Selecciona el banco de la cuenta.");
      return;
    }
    if (!label.trim()) {
      window.alert("El nombre de la cuenta es obligatorio.");
      return;
    }
    setBusy(true);
    try {
      const line = businessLine
        ? (businessLine as TransactionDomain)
        : undefined;
      if (editingId) {
        // No `currency`: see the file header.
        await updateBankAccount(editingId, {
          bankId,
          label: label.trim(),
          businessLine: line,
          active,
        });
      } else {
        await createBankAccount({
          bankId,
          label: label.trim(),
          currency,
          businessLine: line,
          active,
        });
      }
      cancel();
      onChanged();
    } catch (e) {
      window.alert((e as Error)?.message ?? "No se pudo guardar la cuenta.");
    } finally {
      setBusy(false);
    }
  }

  const editor = (
    <div className="child-editor">
      <div className="form-grid">
        <label className="field">
          <span className="field-label">
            Banco <span aria-hidden>*</span>
          </span>
          <select
            className="select"
            value={bankId}
            onChange={(e) => setBankId(e.target.value)}
          >
            <option value="">—</option>
            {banks.map((b) => (
              <option key={b.id} value={b.id}>
                {b.name}
              </option>
            ))}
          </select>
        </label>
        <label className="field">
          <span className="field-label">
            Nombre de la cuenta <span aria-hidden>*</span>
          </span>
          <input
            className="input"
            value={label}
            onChange={(e) => setLabel(e.target.value)}
            placeholder="Ej. Seguros — Bank of America (USD)"
          />
        </label>
        <label className="field">
          <span className="field-label">
            Moneda <span aria-hidden>*</span>
          </span>
          <select
            className="select"
            value={currency}
            disabled={editingId !== null}
            onChange={(e) => setCurrency(e.target.value as Currency)}
          >
            {CURRENCIES.map((c) => (
              <option key={c} value={c}>
                {c}
              </option>
            ))}
          </select>
          {editingId !== null && (
            <span className="section-note">
              No se puede cambiar: los movimientos ya registrados están en esta
              moneda.
            </span>
          )}
        </label>
        <label className="field">
          <span className="field-label">Línea de negocio</span>
          <select
            className="select"
            value={businessLine}
            onChange={(e) => setBusinessLine(e.target.value)}
          >
            <option value="">Sin asignar</option>
            {BUSINESS_LINES.map((d) => (
              <option key={d} value={d}>
                {domainLabel(d)}
              </option>
            ))}
          </select>
          <span className="section-note">
            Referencia nada más: una chequera puede pagar de varias líneas.
          </span>
        </label>
        <label
          className="field"
          style={{ flexDirection: "row", alignItems: "center", gap: 8 }}
        >
          <input
            type="checkbox"
            checked={active}
            onChange={(e) => setActive(e.target.checked)}
          />
          <span className="field-label" style={{ margin: 0 }}>
            Cuenta abierta
          </span>
        </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 }}>
          Cuentas
          <span className="section-count"> {accounts.length}</span>
        </h3>
        {!adding && editingId === null && banks.length > 0 && (
          <button type="button" className="btn btn-outline" onClick={startAdd}>
            + Agregar
          </button>
        )}
      </div>

      {banks.length === 0 ? (
        <div className="empty-inline">
          Registra primero el banco donde está la cuenta.
        </div>
      ) : accounts.length === 0 && !adding ? (
        <div className="empty-inline">Sin cuentas registradas.</div>
      ) : (
        <div className="tx-scroll">
          <table className="tx-table">
            <thead>
              <tr>
                <th>Cuenta</th>
                <th>Banco</th>
                <th>Moneda</th>
                <th>Línea</th>
                <th>Estatus</th>
                <th className="num">Acciones</th>
              </tr>
            </thead>
            <tbody>
              {adding && (
                <tr>
                  <td colSpan={6}>{editor}</td>
                </tr>
              )}
              {accounts.map((a) =>
                editingId === a.id ? (
                  <tr key={a.id}>
                    <td colSpan={6}>{editor}</td>
                  </tr>
                ) : (
                  <tr key={a.id}>
                    <td>{a.label}</td>
                    <td>{a.bankName}</td>
                    <td className="mono">{a.currency}</td>
                    <td>{a.businessLine ? domainLabel(a.businessLine) : "—"}</td>
                    <td>{a.active ? "Abierta" : "Cerrada"}</td>
                    <td>
                      <div className="row-actions">
                        <button
                          type="button"
                          className="btn btn-ghost"
                          onClick={() => startEdit(a)}
                        >
                          Editar
                        </button>
                        <Link href="/banco" className="btn btn-ghost">
                          Ver movimientos
                        </Link>
                      </div>
                    </td>
                  </tr>
                ),
              )}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}
