"use client";

import { useCallback, useEffect, useMemo, useState, type FormEvent } from "react";
import { supabase } from "@/lib/supabase";
import PageLayout from "@/components/layout/PageLayout";
import Card from "@/components/ui/Card";
import Input from "@/components/ui/Input";
import Select from "@/components/ui/Select";
import Button from "@/components/ui/Button";
import Badge from "@/components/ui/Badge";
import Modal from "@/components/ui/Modal";

type DbId = number | string;
type NumericValue = number | string | null;

type Recibo = {
  id: DbId;
  numero: string | null;
  numero_guia: string | null;
  cliente: string | null;
  monto: NumericValue;
  estado: string | null;
  fecha: string | null;
};

type Pago = {
  id: DbId;
  recibo_id: DbId | null;
  recibo_numero_snapshot: string | null;
  recibo_numero_guia_snapshot: string | null;
  recibo_cliente_snapshot: string | null;
  recibo_monto_snapshot: NumericValue;
  cliente: string;
  monto: NumericValue;
  moneda: string;
  metodo_pago: string;
  referencia: string | null;
  fecha: string;
  notas: string | null;
  created_at: string | null;
};

type FiltroEstado = "todos" | "pendientes" | "pagadas";
type PageResult<T> = {
  data: T[] | null;
  error: { message: string } | null;
};

const metodosPago = [
  { value: "Efectivo", label: "Efectivo" },
  { value: "Zelle", label: "Zelle" },
  { value: "Transferencia bancaria", label: "Transferencia bancaria" },
  { value: "Tarjeta", label: "Tarjeta" },
  { value: "PayPal", label: "PayPal" },
  { value: "Otro", label: "Otro" },
];

function fechaLocal(): string {
  const ahora = new Date();
  ahora.setMinutes(ahora.getMinutes() - ahora.getTimezoneOffset());
  return ahora.toISOString().slice(0, 10);
}

function aCentavos(valor: NumericValue): number | null {
  if (valor === null || valor === "") return null;
  const texto = String(valor).trim();
  const coincidencia = /^(-?)(\d+)(?:\.(\d{1,2}))?$/.exec(texto);
  if (!coincidencia) return null;

  const unidades = Number(coincidencia[2]);
  const fraccion = Number((coincidencia[3] || "").padEnd(2, "0"));
  const centavos = unidades * 100 + fraccion;
  if (!Number.isSafeInteger(centavos)) return null;
  return coincidencia[1] ? -centavos : centavos;
}

function dinero(centavos: number): string {
  return new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
  }).format(centavos / 100);
}

function idClave(id: DbId): string {
  return String(id);
}

function compararIdsDesc(a: DbId, b: DbId): number {
  const idA = BigInt(a);
  const idB = BigInt(b);
  return idA > idB ? -1 : idA < idB ? 1 : 0;
}

function fechaValida(fecha: string): boolean {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(fecha)) return false;
  const parsed = new Date(`${fecha}T00:00:00Z`);
  return !Number.isNaN(parsed.getTime()) && parsed.toISOString().slice(0, 10) === fecha;
}

function mostrarFecha(fecha: string | null): string {
  if (!fecha) return "Sin fecha";
  const parsed = new Date(`${fecha.slice(0, 10)}T00:00:00`);
  return Number.isNaN(parsed.getTime())
    ? fecha
    : new Intl.DateTimeFormat("es-HN", { dateStyle: "medium" }).format(parsed);
}

async function cargarRecibosPaginados(): Promise<PageResult<Recibo>> {
  const filas: Recibo[] = [];
  const tamanoPagina = 1000;

  for (let desde = 0; ; desde += tamanoPagina) {
    const { data, error } = await supabase
      .from("hce_recibos")
      .select("id, numero, numero_guia, cliente, monto, estado, fecha")
      .order("id", { ascending: true })
      .range(desde, desde + tamanoPagina - 1);

    if (error) return { data: null, error };
    const pagina = (data || []) as Recibo[];
    filas.push(...pagina);
    if (pagina.length < tamanoPagina) break;
  }

  return { data: filas, error: null };
}

async function cargarPagosPaginados(): Promise<PageResult<Pago>> {
  try {
    const response = await fetch("/cargoerp/api/pagos", {
      method: "GET",
      credentials: "include",
    });

    const result = (await response.json()) as {
      success?: boolean;
      pagos?: Pago[];
      error?: string;
    };

    if (!response.ok || !result.success) {
      return {
        data: null,
        error: { message: result.error || `Error HTTP ${response.status}.` },
      };
    }

    const filas = (result.pagos || []) as Pago[];
    filas.sort(
      (a, b) =>
        b.fecha.localeCompare(a.fecha) || compararIdsDesc(a.id, b.id)
    );
    return { data: filas, error: null };
  } catch (error) {
    return {
      data: null,
      error: {
        message:
          error instanceof Error
            ? error.message
            : "Error de conexión al cargar pagos.",
      },
    };
  }
}

export default function PagosPage() {
  const [recibos, setRecibos] = useState<Recibo[]>([]);
  const [pagos, setPagos] = useState<Pago[]>([]);
  const [loading, setLoading] = useState(true);
  const [errorCarga, setErrorCarga] = useState("");
  const [busqueda, setBusqueda] = useState("");
  const [filtroEstado, setFiltroEstado] = useState<FiltroEstado>("todos");
  const [reciboActivo, setReciboActivo] = useState<Recibo | null>(null);
  const [monto, setMonto] = useState("");
  const [metodoPago, setMetodoPago] = useState("Efectivo");
  const [fecha, setFecha] = useState(fechaLocal);
  const [referencia, setReferencia] = useState("");
  const [observaciones, setObservaciones] = useState("");
  const [errorFormulario, setErrorFormulario] = useState("");
  const [guardando, setGuardando] = useState(false);
  const [mensajeExito, setMensajeExito] = useState("");

  const cargarDatos = useCallback(async (mostrarCarga = true) => {
    if (mostrarCarga) setLoading(true);
    setErrorCarga("");

    const [recibosResult, pagosResult] = await Promise.all([
      cargarRecibosPaginados(),
      cargarPagosPaginados(),
    ]);

    if (recibosResult.error || pagosResult.error) {
      const errores = [
        recibosResult.error
          ? `No se pudieron consultar los recibos: ${recibosResult.error.message}`
          : "",
        pagosResult.error
          ? `No se pudieron consultar los pagos: ${pagosResult.error.message}`
          : "",
      ].filter(Boolean);
      setErrorCarga(
        `${errores.join(" ")} Si el error menciona que no existe la tabla o columna hce_abonos, falta aplicar la migración en el entorno de pruebas.`
      );
      setLoading(false);
      return;
    }

    setRecibos(recibosResult.data || []);
    setPagos(pagosResult.data || []);
    setLoading(false);
  }, []);

  useEffect(() => {
    void cargarDatos();
  }, [cargarDatos]);

  const pagosPorRecibo = useMemo(() => {
    const agrupados = new Map<string, Pago[]>();
    for (const pago of pagos) {
      if (pago.recibo_id === null) continue;
      const key = idClave(pago.recibo_id);
      const grupo = agrupados.get(key) || [];
      grupo.push(pago);
      agrupados.set(key, grupo);
    }
    return agrupados;
  }, [pagos]);

  const pagosHistoricos = useMemo(
    () => pagos.filter((pago) => pago.recibo_id === null),
    [pagos]
  );
  const pagosDeRecibosNoVisibles = useMemo(() => {
    const idsVisibles = new Set(recibos.map((recibo) => idClave(recibo.id)));
    return pagos.filter(
      (pago) =>
        pago.recibo_id !== null && !idsVisibles.has(idClave(pago.recibo_id))
    );
  }, [pagos, recibos]);

  const recibosConSaldo = useMemo(
    () =>
      recibos.map((recibo) => {
        const totalCents = aCentavos(recibo.monto);
        const historial = pagosPorRecibo.get(idClave(recibo.id)) || [];
        const abonadoCents = historial.reduce(
          (total, pago) => total + (aCentavos(pago.monto) || 0),
          0
        );
        const saldoCents =
          totalCents === null ? null : Math.max(0, totalCents - abonadoCents);
        return { recibo, totalCents, abonadoCents, saldoCents, historial };
      }),
    [recibos, pagosPorRecibo]
  );

  const recibosFiltrados = useMemo(() => {
    const texto = busqueda.trim().toLocaleLowerCase();
    return recibosConSaldo.filter(({ recibo, saldoCents }) => {
      const coincideTexto =
        !texto ||
        [
          recibo.cliente,
          recibo.numero,
          recibo.numero_guia,
          String(recibo.id),
        ].some((valor) => valor?.toLocaleLowerCase().includes(texto));
      const estaPagada = saldoCents === 0;
      const coincideEstado =
        filtroEstado === "todos" ||
        (filtroEstado === "pagadas" && estaPagada) ||
        (filtroEstado === "pendientes" && !estaPagada);
      return coincideTexto && coincideEstado;
    });
  }, [busqueda, filtroEstado, recibosConSaldo]);

  const totalAbonadoVinculado = pagos
    .filter((pago) => pago.recibo_id !== null)
    .reduce((total, pago) => total + (aCentavos(pago.monto) || 0), 0);
  const totalPendiente = recibosConSaldo.reduce(
    (total, item) => total + (item.saldoCents || 0),
    0
  );
  const recibosPendientes = recibosConSaldo.filter(
    (item) => item.saldoCents !== null && item.saldoCents > 0
  ).length;

  function abrirFormulario(recibo: Recibo) {
    setReciboActivo(recibo);
    setMensajeExito("");
    setMonto("");
    setMetodoPago("Efectivo");
    setFecha(fechaLocal());
    setReferencia("");
    setObservaciones("");
    setErrorFormulario("");
  }

  function cerrarFormulario() {
    if (guardando) return;
    setReciboActivo(null);
    setErrorFormulario("");
  }

  async function registrarAbono(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!reciboActivo) return;
    setErrorFormulario("");

    const importeCents = aCentavos(monto);
    const reciboActual = recibosConSaldo.find(
      (item) => idClave(item.recibo.id) === idClave(reciboActivo.id)
    );

    if (importeCents === null || importeCents <= 0) {
      setErrorFormulario("Ingresa un importe válido mayor que $0.00, con hasta dos decimales.");
      return;
    }
    if (!fechaValida(fecha)) {
      setErrorFormulario("Selecciona una fecha válida.");
      return;
    }
    if (!reciboActual || reciboActual.saldoCents === null) {
      setErrorFormulario("El recibo no tiene un importe válido para calcular el saldo.");
      return;
    }
    if (importeCents > reciboActual.saldoCents) {
      setErrorFormulario(
        `El abono supera el saldo disponible de ${dinero(reciboActual.saldoCents)}.`
      );
      return;
    }

    setGuardando(true);

    try {
      const response = await fetch("/cargoerp/api/pagos/abonos", {
        method: "POST",
        credentials: "include",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          reciboId: String(reciboActivo.id),
          monto: (importeCents / 100).toFixed(2),
          metodoPago,
          referencia: referencia.trim() || null,
          fecha,
          observaciones: observaciones.trim() || null,
        }),
      });

      const result = (await response.json()) as {
        success?: boolean;
        error?: string;
      };
      if (!response.ok || !result.success) {
        throw new Error(result.error || `Error HTTP ${response.status}.`);
      }
    } catch (error) {
      const detalle =
        error instanceof Error ? error.message : "Error de conexión desconocido.";
      console.error("Error registrando abono:", error);
      setErrorFormulario(
        `No se pudo registrar el abono: ${detalle}. Si dos abonos se enviaron simultáneamente, el servidor rechazará el que exceda el saldo actualizado.`
      );
      setGuardando(false);
      return;
    }

    setMensajeExito(
      `Abono de ${dinero(importeCents)} guardado. El saldo de este recibo quedó en ${dinero(
        Math.max(0, reciboActual.saldoCents - importeCents)
      )}.`
    );
    setReciboActivo(null);
    setGuardando(false);
    await cargarDatos(false);
  }

  const opcionesEstado = [
    { value: "todos", label: "Todos los recibos" },
    { value: "pendientes", label: "Pendientes" },
    { value: "pagadas", label: "Pagadas" },
  ];

  return (
    <PageLayout>
      <section className="mb-5">
        <h1 className="text-xl font-black text-[var(--text-primary)] lg:text-2xl">
          Pagos
        </h1>
        <p className="mt-1 text-sm text-[var(--text-muted)]">
          Deudas y abonos independientes por recibo. El estado se calcula aquí sin modificar el recibo.
        </p>
      </section>

      {mensajeExito && (
        <div
          role="status"
          className="mb-4 rounded-xl border border-emerald-500/20 bg-emerald-500/10 p-3 text-sm text-emerald-700 dark:text-emerald-300"
        >
          {mensajeExito}
        </div>
      )}

      <div className="mb-5 grid grid-cols-1 gap-3 sm:grid-cols-3">
        <ResumenCard titulo="Saldo pendiente" valor={dinero(totalPendiente)} color="text-red-500" />
        <ResumenCard
          titulo="Abonos vinculados"
          valor={dinero(totalAbonadoVinculado)}
          color="text-emerald-500"
        />
        <ResumenCard
          titulo="Recibos pendientes"
          valor={String(recibosPendientes)}
          color="text-[var(--accent)]"
        />
      </div>

      <Card className="mb-5" padding="sm">
        <div className="grid grid-cols-1 gap-3 md:grid-cols-[minmax(0,1fr)_230px]">
          <Input
            label="Buscar remitente, recibo o guía"
            placeholder="Nombre, número de recibo o guía"
            value={busqueda}
            onChange={(event) => setBusqueda(event.target.value)}
          />
          <Select
            label="Estado de cuenta"
            options={opcionesEstado}
            value={filtroEstado}
            onChange={(event) => setFiltroEstado(event.target.value as FiltroEstado)}
          />
        </div>
      </Card>

      {loading ? (
        <Card>
          <p className="py-8 text-center text-sm text-[var(--text-muted)]">
            Cargando recibos y pagos...
          </p>
        </Card>
      ) : errorCarga ? (
        <Card>
          <div role="alert" className="space-y-3 text-sm text-red-500">
            <p>{errorCarga}</p>
            <Button variant="secondary" size="sm" onClick={() => void cargarDatos()}>
              Reintentar
            </Button>
          </div>
        </Card>
      ) : (
        <>
          <section aria-labelledby="cuentas-heading">
            <div className="mb-3 flex flex-wrap items-end justify-between gap-2">
              <div>
                <h2
                  id="cuentas-heading"
                  className="text-base font-black text-[var(--text-primary)]"
                >
                  Cuentas por recibo
                </h2>
                <p className="text-xs text-[var(--text-muted)]">
                  Cada recibo mantiene su propio saldo, incluso si el remitente tiene varios.
                </p>
              </div>
              <span className="text-xs text-[var(--text-muted)]">
                {recibosFiltrados.length} recibos
              </span>
            </div>

            {recibosFiltrados.length === 0 ? (
              <Card>
                <p className="py-6 text-center text-sm text-[var(--text-muted)]">
                  {recibos.length === 0
                    ? "No hay recibos para mostrar."
                    : "No hay recibos que coincidan con la búsqueda y el filtro."}
                </p>
              </Card>
            ) : (
              <div className="space-y-3">
                {recibosFiltrados.map(
                  ({ recibo, totalCents, abonadoCents, saldoCents, historial }) => {
                    const montoValido = totalCents !== null;
                    const pagada =
                      montoValido &&
                      totalCents > 0 &&
                      saldoCents === 0;

                    return (
                      <Card key={idClave(recibo.id)} padding="sm">
                        <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
                          <div className="min-w-0 flex-1">
                            <div className="flex flex-wrap items-center gap-2">
                              <h3 className="text-base font-bold text-[var(--text-primary)]">
                                {recibo.cliente?.trim() || "Remitente no indicado"}
                              </h3>
                              <Badge variant={pagada ? "success" : "danger"} size="sm">
                                {pagada ? "PAGADA" : "PENDIENTE"}
                              </Badge>
                            </div>
                            <div className="mt-1 flex flex-wrap gap-x-4 gap-y-1 text-xs text-[var(--text-muted)]">
                              <span>Recibo: {recibo.numero || recibo.id}</span>
                              <span>Guía: {recibo.numero_guia || "—"}</span>
                              <span>Fecha: {mostrarFecha(recibo.fecha)}</span>
                            </div>
                          </div>

                          <div className="grid grid-cols-3 gap-3 text-right lg:min-w-[390px]">
                            <ImporteResumen label="Original" cents={totalCents} />
                            <ImporteResumen label="Abonado" cents={abonadoCents} />
                            <ImporteResumen
                              label="Pendiente"
                              cents={saldoCents}
                              destacado
                            />
                          </div>
                        </div>

                        <div className="mt-4 border-t border-[var(--border)] pt-3">
                          <div className="mb-2 flex items-center justify-between gap-2">
                            <h4 className="text-xs font-bold uppercase tracking-wide text-[var(--text-secondary)]">
                              Historial de abonos ({historial.length})
                            </h4>
                            {!pagada && montoValido && saldoCents !== null && saldoCents > 0 && (
                              <Button
                                size="sm"
                                onClick={() => abrirFormulario(recibo)}
                              >
                                Registrar abono
                              </Button>
                            )}
                          </div>

                          {historial.length === 0 ? (
                            <p className="py-2 text-xs text-[var(--text-muted)]">
                              Este recibo aún no tiene abonos vinculados.
                            </p>
                          ) : (
                            <div className="divide-y divide-[var(--border)]">
                              {historial.map((pago) => (
                                <div
                                  key={idClave(pago.id)}
                                  className="grid grid-cols-2 gap-2 py-2 text-xs sm:grid-cols-[1fr_1fr_1fr_1fr_2fr]"
                                >
                                  <span className="font-semibold text-emerald-600 dark:text-emerald-400">
                                    {dinero(aCentavos(pago.monto) || 0)}
                                  </span>
                                  <span className="text-[var(--text-secondary)]">
                                    {pago.metodo_pago}
                                  </span>
                                  <span className="text-[var(--text-secondary)]">
                                    {mostrarFecha(pago.fecha)}
                                  </span>
                                  <span className="text-[var(--text-muted)]">
                                    {pago.referencia || "Sin referencia"}
                                  </span>
                                  <span className="col-span-2 text-[var(--text-muted)] sm:col-span-1">
                                    {pago.notas || "Sin observaciones"}
                                  </span>
                                </div>
                              ))}
                            </div>
                          )}
                        </div>
                      </Card>
                    );
                  }
                )}
              </div>
            )}
          </section>

          <section className="mt-7" aria-labelledby="historicos-heading">
            <div className="mb-3">
              <h2
                id="historicos-heading"
                className="text-base font-black text-[var(--text-primary)]"
              >
                Pagos históricos sin recibo asignado
              </h2>
              <p className="text-xs text-[var(--text-muted)]">
                Se conservan tal como están y no reducen el saldo de ningún recibo.
              </p>
            </div>
            {pagosHistoricos.length === 0 ? (
              <Card>
                <p className="py-5 text-center text-sm text-[var(--text-muted)]">
                  No hay pagos históricos sin vincular.
                </p>
              </Card>
            ) : (
              <Card padding="none">
                <div className="divide-y divide-[var(--border)]">
                  {pagosHistoricos.map((pago) => (
                    <div
                      key={idClave(pago.id)}
                      className="grid grid-cols-2 gap-2 p-3 text-sm sm:grid-cols-[2fr_1fr_1fr_1fr_2fr]"
                    >
                      <div>
                        <p className="font-semibold text-[var(--text-primary)]">
                          {pago.cliente}
                        </p>
                        <p className="text-xs text-[var(--text-muted)]">
                          Pago histórico · sin recibo vinculado
                        </p>
                      </div>
                      <span className="font-bold text-emerald-600 dark:text-emerald-400">
                        {dinero(aCentavos(pago.monto) || 0)}
                      </span>
                      <span className="text-[var(--text-secondary)]">{pago.metodo_pago}</span>
                      <span className="text-[var(--text-secondary)]">
                        {mostrarFecha(pago.fecha)}
                      </span>
                      <span className="text-xs text-[var(--text-muted)]">
                        {[pago.referencia, pago.notas].filter(Boolean).join(" · ") || "—"}
                      </span>
                    </div>
                  ))}
                </div>
              </Card>
            )}
          </section>

          {pagosDeRecibosNoVisibles.length > 0 && (
            <section className="mt-7" aria-labelledby="recibos-no-visibles-heading">
              <div className="mb-3">
                <h2
                  id="recibos-no-visibles-heading"
                  className="text-base font-black text-[var(--text-primary)]"
                >
                  Abonos con recibo eliminado o no visible
                </h2>
                <p className="text-xs text-[var(--text-muted)]">
                  El ID y los datos guardados del recibo se conservan en el historial; estos abonos no se reasignan.
                </p>
              </div>
              <Card padding="none">
                <div className="divide-y divide-[var(--border)]">
                  {pagosDeRecibosNoVisibles.map((pago) => (
                    <div
                      key={idClave(pago.id)}
                      className="grid grid-cols-2 gap-2 p-3 text-sm sm:grid-cols-[2fr_1fr_1fr_1fr_2fr]"
                    >
                      <div>
                        <p className="font-semibold text-[var(--text-primary)]">
                          {pago.recibo_cliente_snapshot || pago.cliente}
                        </p>
                        <p className="text-xs text-[var(--text-muted)]">
                          Recibo {pago.recibo_numero_snapshot || pago.recibo_id}
                          {pago.recibo_numero_guia_snapshot
                            ? ` · Guía ${pago.recibo_numero_guia_snapshot}`
                            : ""}
                          {pago.recibo_monto_snapshot !== null
                            ? ` · Original ${dinero(
                                aCentavos(pago.recibo_monto_snapshot) || 0
                              )}`
                            : ""}
                        </p>
                      </div>
                      <span className="font-bold text-emerald-600 dark:text-emerald-400">
                        {dinero(aCentavos(pago.monto) || 0)}
                      </span>
                      <span className="text-[var(--text-secondary)]">{pago.metodo_pago}</span>
                      <span className="text-[var(--text-secondary)]">
                        {mostrarFecha(pago.fecha)}
                      </span>
                      <span className="text-xs text-[var(--text-muted)]">
                        {[pago.referencia, pago.notas].filter(Boolean).join(" · ") || "—"}
                      </span>
                    </div>
                  ))}
                </div>
              </Card>
            </section>
          )}
        </>
      )}

      <Modal
        isOpen={reciboActivo !== null}
        onClose={cerrarFormulario}
        title="Registrar abono"
        description={
          reciboActivo
            ? `${reciboActivo.cliente || "Remitente no indicado"} · Recibo ${
                reciboActivo.numero || reciboActivo.id
              }`
            : undefined
        }
      >
        {reciboActivo && (
          <form onSubmit={registrarAbono} className="space-y-4">
            <div className="rounded-xl border border-[var(--border)] bg-[var(--bg-primary)] p-3 text-sm">
              <p className="text-[var(--text-muted)]">Saldo pendiente actual</p>
              <p className="mt-1 text-xl font-black text-[var(--accent)]">
                {dinero(
                  recibosConSaldo.find(
                    (item) => idClave(item.recibo.id) === idClave(reciboActivo.id)
                  )?.saldoCents || 0
                )}
              </p>
            </div>

            <Input
              label="Importe del abono (USD)"
              type="number"
              min="0.01"
              step="0.01"
              max={(
                (recibosConSaldo.find(
                  (item) => idClave(item.recibo.id) === idClave(reciboActivo.id)
                )?.saldoCents || 0) / 100
              ).toFixed(2)}
              placeholder="150.00"
              value={monto}
              onChange={(event) => setMonto(event.target.value)}
              required
            />
            <Select
              label="Método de pago"
              options={metodosPago}
              value={metodoPago}
              onChange={(event) => setMetodoPago(event.target.value)}
              required
            />
            <Input
              label="Fecha"
              type="date"
              value={fecha}
              onChange={(event) => setFecha(event.target.value)}
              required
            />
            <Input
              label="Referencia (opcional)"
              placeholder="Número de transacción"
              value={referencia}
              onChange={(event) => setReferencia(event.target.value)}
            />
            <label className="block text-sm font-medium text-[var(--text-secondary)]">
              Observaciones (opcional)
              <textarea
                className="mt-1.5 min-h-24 w-full rounded-xl border border-[var(--border)] bg-[var(--input-bg)] px-3 py-2.5 text-sm text-[var(--text-primary)] outline-none focus:border-[var(--accent)]"
                value={observaciones}
                onChange={(event) => setObservaciones(event.target.value)}
                maxLength={2000}
              />
            </label>

            {errorFormulario && (
              <p role="alert" className="rounded-lg bg-red-500/10 p-3 text-sm text-red-600">
                {errorFormulario}
              </p>
            )}

            <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
              <Button
                variant="ghost"
                onClick={cerrarFormulario}
                disabled={guardando}
              >
                Cancelar
              </Button>
              <Button type="submit" disabled={guardando}>
                {guardando ? "Guardando..." : "Guardar abono"}
              </Button>
            </div>
          </form>
        )}
      </Modal>
    </PageLayout>
  );
}

function ResumenCard({
  titulo,
  valor,
  color,
}: {
  titulo: string;
  valor: string;
  color: string;
}) {
  return (
    <Card padding="sm">
      <p className="text-[10px] font-bold uppercase tracking-wider text-[var(--text-muted)]">
        {titulo}
      </p>
      <p className={`mt-1 text-base font-black ${color}`}>{valor}</p>
    </Card>
  );
}

function ImporteResumen({
  label,
  cents,
  destacado = false,
}: {
  label: string;
  cents: number | null;
  destacado?: boolean;
}) {
  return (
    <div>
      <p className="text-[10px] font-semibold uppercase tracking-wide text-[var(--text-muted)]">
        {label}
      </p>
      <p
        className={`mt-1 text-sm font-bold ${
          destacado ? "text-[var(--accent)]" : "text-[var(--text-primary)]"
        }`}
      >
        {cents === null ? "—" : dinero(cents)}
      </p>
    </div>
  );
}
