"use client";

import { useCallback, useEffect, useState } from "react";
import { api, type AjustesDeOrden, type Orden, type TipoAjuste } from "@/lib/api";
import { valorDeAjuste } from "@/lib/ajustes";
import { admiteAjustesNuevos, muestraAjustes, productosAjustables } from "@/lib/costos-reglas";
import { usePuede } from "@/components/sesion-proveedor";
import { leerNombre } from "@/lib/producto";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { toast } from "sonner";

const ETIQUETAS: Record<TipoAjuste, string> = {
  MATERIALES: "Materiales",
  MANO_OBRA: "Mano de obra",
  GASTO_FABRICACION: "Gastos de fabricación",
  INDIRECTO: "Indirectos",
};

/** Un decimal exacto en texto («10089.418734») con miles y sin pasar por `Number`. */
function formato(t: string | null): string {
  if (null === t) return "—";
  const [entero, frac = ""] = t.split(".");
  const signo = entero.startsWith("-") ? "-" : "";
  const miles = entero.replace("-", "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");

  return `${signo}${miles}${"" === frac ? "" : "." + frac}`;
}

/**
 * Datos tardíos de una orden ya cerrada (P10c de #24981). El costo con el que cerró NO cambia: lo que llega tarde (una
 * factura, una tarifa corregida) se registra como ajuste, con su concepto y su motivo, y el costo ajustado se ve al lado.
 * Por ahora un ajuste no mueve inventario: lo materializa el motor de costos (fase 2).
 */
export function AjustesOrden({ orden }: { orden: Orden }) {
  const puedeVer = usePuede("ver");
  const puedeRegistrar = usePuede("registrar_produccion");
  // Una orden cerrada que luego se anula conserva su costo congelado y sus ajustes: se sigue mostrando (sin registrar nuevos).
  const cerrada = muestraAjustes(orden.estado, orden.cerradoEn);
  const admiteAjustes = admiteAjustesNuevos(orden.estado);

  const [datos, setDatos] = useState<AjustesDeOrden | null>(null);
  const [falloLectura, setFalloLectura] = useState(false);
  const [trabajando, setTrabajando] = useState(false);
  const [f, setF] = useState({ pluProducto: "", tipo: "MATERIALES" as TipoAjuste, concepto: "", valor: "", motivo: "", fecha: "" });

  const cargar = useCallback(async () => {
    if (!cerrada || !puedeVer) return;
    try {
      setDatos(await api<AjustesDeOrden>(`/api/ordenes/${orden.id}/ajustes`));
      setFalloLectura(false);
    } catch (error) {
      setFalloLectura(true);
      toast.error(error instanceof Error ? error.message : "No se pudieron leer los ajustes.");
    }
  }, [orden.id, cerrada, puedeVer]);

  useEffect(() => {
    void cargar();
  }, [cargar]);

  if (!cerrada || !puedeVer) return null;

  // Sólo los productos que produjeron algo; el elegido es el primero de ellos mientras no se haya elegido otro válido.
  const ajustables = productosAjustables(orden.detalles);
  const pluElegido = ajustables.some((d) => d.plu === f.pluProducto) ? f.pluProducto : (ajustables[0]?.plu ?? "");
  const valor = valorDeAjuste(f.valor);
  const completo = null !== valor && "" !== f.concepto.trim() && "" !== f.motivo.trim() && "" !== pluElegido;

  async function registrar() {
    if (null === valor) return;
    setTrabajando(true);
    try {
      setDatos(
        await api<AjustesDeOrden>(`/api/ordenes/${orden.id}/ajustes`, {
          metodo: "POST",
          cuerpo: {
            pluProducto: pluElegido,
            tipo: f.tipo,
            concepto: f.concepto.trim(),
            valor, // texto, nunca Number
            motivo: f.motivo.trim(),
            fecha: f.fecha || undefined,
          },
        }),
      );
      setF((p) => ({ ...p, concepto: "", valor: "", motivo: "", fecha: "" }));
      toast.success("Ajuste registrado. El costo con el que cerró no cambió.");
    } catch (error) {
      toast.error(error instanceof Error ? error.message : "No se pudo registrar el ajuste.", { duration: 10000 });
    } finally {
      setTrabajando(false);
    }
  }

  return (
    <Card className="min-w-0">
      <CardHeader>
        <CardTitle className="text-base">Ajustes tardíos</CardTitle>
        <CardDescription>
          La orden ya cerró y su costo quedó congelado. Un dato que llega tarde se registra acá, con su motivo; no reescribe el cierre.
        </CardDescription>
      </CardHeader>
      <CardContent className="space-y-4">
        {falloLectura ? (
          <p className="text-sm text-amber-600">No se pudieron leer los ajustes: no se sabe si hay alguno. Recargue la página.</p>
        ) : null === datos ? (
          <p className="text-sm text-muted-foreground">Cargando…</p>
        ) : (
          <>
            <dl className="grid gap-2 text-sm sm:grid-cols-3">
              <div>
                <dt className="text-muted-foreground">Costo real con el que cerró</dt>
                <dd className="tabular-nums font-medium">{formato(datos.costoRealCongelado)}</dd>
              </div>
              <div>
                <dt className="text-muted-foreground">Ajustes</dt>
                <dd className="tabular-nums font-medium">{formato(datos.totalAjustes)}</dd>
              </div>
              <div>
                <dt className="text-muted-foreground">Costo ajustado</dt>
                <dd className="tabular-nums font-medium">{formato(datos.costoRealAjustado)}</dd>
              </div>
            </dl>

            {datos.ajustes.length > 0 ? (
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Fecha</TableHead>
                    <TableHead>Producto</TableHead>
                    <TableHead>Bloque</TableHead>
                    <TableHead>Concepto y motivo</TableHead>
                    <TableHead className="text-right">Valor</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {datos.ajustes.map((a) => (
                    <TableRow key={a.id}>
                      <TableCell className="tabular-nums">{a.fecha}</TableCell>
                      <TableCell>{leerNombre(orden.detalles.find((d) => d.plu === a.pluProducto)?.descripcion ?? a.pluProducto).nombre}</TableCell>
                      <TableCell>{ETIQUETAS[a.tipo]}</TableCell>
                      <TableCell>
                        <div>{a.concepto}</div>
                        <div className="text-xs text-muted-foreground">{a.motivo}</div>
                      </TableCell>
                      <TableCell className="text-right tabular-nums">{formato(a.valor)}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            ) : (
              <p className="text-sm text-muted-foreground">Esta orden no tiene ajustes.</p>
            )}
            {datos.avisos.map((a) => (
              <p key={a} className="text-xs text-muted-foreground">
                {a}
              </p>
            ))}
          </>
        )}

        {puedeRegistrar && admiteAjustes && null !== datos && !falloLectura ? (
          <div className="space-y-3 rounded-lg border p-3">
            <div className="text-sm font-medium">Registrar un ajuste</div>
            <div className="grid gap-3 sm:grid-cols-2">
              <div className="space-y-1">
                <Label htmlFor="aj-producto">Producto</Label>
                <select id="aj-producto" className="h-9 w-full rounded-md border bg-transparent px-2 text-sm" value={pluElegido} onChange={(e) => setF((p) => ({ ...p, pluProducto: e.target.value }))}>
                  {ajustables.map((d) => (
                    <option key={d.plu} value={d.plu}>
                      {leerNombre(d.descripcion ?? d.plu).nombre}
                    </option>
                  ))}
                </select>
              </div>
              <div className="space-y-1">
                <Label htmlFor="aj-tipo">Bloque</Label>
                <select id="aj-tipo" className="h-9 w-full rounded-md border bg-transparent px-2 text-sm" value={f.tipo} onChange={(e) => setF((p) => ({ ...p, tipo: e.target.value as TipoAjuste }))}>
                  {(Object.keys(ETIQUETAS) as TipoAjuste[]).map((t) => (
                    <option key={t} value={t}>
                      {ETIQUETAS[t]}
                    </option>
                  ))}
                </select>
              </div>
              <div className="space-y-1">
                <Label htmlFor="aj-concepto">¿A qué corresponde? (la factura, la tarifa, el insumo)</Label>
                <Input id="aj-concepto" maxLength={255} value={f.concepto} onChange={(e) => setF((p) => ({ ...p, concepto: e.target.value }))} />
              </div>
              <div className="space-y-1">
                <Label htmlFor="aj-valor">Valor (negativo si baja el costo)</Label>
                <Input id="aj-valor" inputMode="decimal" value={f.valor} onChange={(e) => setF((p) => ({ ...p, valor: e.target.value }))} placeholder="12.50" />
                {"" !== f.valor.trim() && null === valor ? (
                  <p className="text-xs text-red-600">Escriba un número con hasta 6 decimales, sin separador de miles (por ejemplo 12.50 o -2.25). Cero no es un ajuste.</p>
                ) : null}
              </div>
              <div className="space-y-1">
                <Label htmlFor="aj-fecha">Fecha (opcional, hoy por omisión)</Label>
                <Input id="aj-fecha" type="date" value={f.fecha} onChange={(e) => setF((p) => ({ ...p, fecha: e.target.value }))} />
              </div>
            </div>
            <div className="space-y-1">
              <Label htmlFor="aj-motivo">¿Por qué llegó tarde?</Label>
              <Textarea id="aj-motivo" maxLength={255} value={f.motivo} onChange={(e) => setF((p) => ({ ...p, motivo: e.target.value }))} />
            </div>
            <Button size="sm" disabled={trabajando || !completo} onClick={() => void registrar()}>
              Registrar ajuste
            </Button>
          </div>
        ) : null}
      </CardContent>
    </Card>
  );
}
