import { useMemo, useState } from 'react' import type { Unidad, ParametrosDesarrollo } from '../types' import { obtenerPrecioLista, resolverNumMensualidades } from '../lib/calculations' import { DESARROLLO_DEFAULT } from '../data/desarrollos' import { MENSUALIDADES_DEFAULT, calcularEsquemaFrasa, type EsquemaFrasaResultado, } from '../lib/esquema-frasa' import { SIN_REGLAS, desarrolloEfectivo, type ReglasDesarrollo } from '../lib/reglas' /** Apartado con el que arranca (y se reinicia) el cotizador: cantidad libre */ export const APARTADO_ESQUEMA_DEFAULT = 15000 interface UseCotizacionResult { desarrollo: string /** Cambia de desarrollo: limpia la unidad elegida */ setDesarrollo: (id: string) => void params: ParametrosDesarrollo unidad: Unidad | null setUnidad: (u: Unidad | null) => void acabados: boolean setAcabados: (v: boolean) => void apartado: number setApartado: (v: number) => void /** Apartado aplicado a los cálculos (acotado a >= 0; el vendedor puede apartar con cualquier monto, incluso $0) */ apartadoEfectivo: number /** Número de mensualidades del diferimiento (elección del vendedor, 1..36) */ numMensualidades: number setNumMensualidades: (n: number) => void /** true = la escrituración (5.5%) se difiere con el enganche; false = se paga a la firma */ escrituracionDiferida: boolean setEscrituracionDiferida: (v: boolean) => void precioLista: number /** Esquema FRASA 2026 calculado; null mientras no hay unidad elegida */ resultado: EsquemaFrasaResultado | null /** Meses restantes para la entrega de la unidad (ficha técnica); null si no se pueden resolver */ numMeses: number | null /** Restaura el estado completo desde una cotización guardada (historial) */ restaurar: (estado: EstadoRestaurar) => void /** Reinicia la cotización (botón "Nueva") */ nueva: () => void } export interface EstadoRestaurar { desarrollo: string /** Unidad ya resuelta del inventario cargado */ unidad: Unidad acabados: boolean apartado: number /** Mensualidades del diferimiento guardadas (default 14) */ numMensualidades?: number /** Escrituración diferida guardada (default false) */ escrituracionDiferida?: boolean } /** * Estado central de la cotización con el esquema único FRASA 2026: * desarrollo, unidad, acabados, apartado libre, mensualidades del * diferimiento (1..36, default 14) y si la escrituración se difiere o se paga * a la firma. El resultado sale de calcularEsquemaFrasa (módulo puro, mismo * motor que el API). Ya no hay propuestas: descuentos, enganche en % e índice * de propuesta desaparecieron con las 4 propuestas. */ export function useCotizacion(reglas: ReglasDesarrollo = SIN_REGLAS): UseCotizacionResult { const [desarrollo, setDesarrolloState] = useState(DESARROLLO_DEFAULT) const [unidad, setUnidad] = useState(null) const [acabados, setAcabados] = useState(false) const [apartado, setApartado] = useState(APARTADO_ESQUEMA_DEFAULT) const [numMensualidades, setNumMensualidades] = useState(MENSUALIDADES_DEFAULT) const [escrituracionDiferida, setEscrituracionDiferida] = useState(false) const params = desarrolloEfectivo(reglas, desarrollo) const setDesarrollo = (id: string) => { setDesarrolloState(id) setUnidad(null) setAcabados(false) } const restaurar = (estado: EstadoRestaurar) => { setDesarrolloState(estado.desarrollo) setUnidad(estado.unidad) setAcabados(estado.acabados) setApartado(estado.apartado) setNumMensualidades(estado.numMensualidades ?? MENSUALIDADES_DEFAULT) setEscrituracionDiferida(estado.escrituracionDiferida ?? false) } const nueva = () => { setUnidad(null) setAcabados(false) setApartado(APARTADO_ESQUEMA_DEFAULT) setNumMensualidades(MENSUALIDADES_DEFAULT) setEscrituracionDiferida(false) } const numMeses = useMemo( () => (unidad ? resolverNumMensualidades(unidad, params) : null), [unidad, params], ) const precioLista = useMemo( () => (unidad ? obtenerPrecioLista(unidad, acabados) : 0), [unidad, acabados], ) // Sin mínimo de apartado: el vendedor puede apartar con cualquier monto, // incluso $0; solo se acota a >= 0 como guarda contra capturas raras const apartadoEfectivo = Math.max(0, apartado) const resultado = useMemo(() => { if (!unidad || precioLista <= 0) return null return calcularEsquemaFrasa({ precio: precioLista, apartado: apartadoEfectivo, numMensualidades, escrituracionDiferida, }) }, [unidad, precioLista, apartadoEfectivo, numMensualidades, escrituracionDiferida]) return { desarrollo, setDesarrollo, params, unidad, setUnidad, acabados, setAcabados, apartado, setApartado, apartadoEfectivo, numMensualidades, setNumMensualidades, escrituracionDiferida, setEscrituracionDiferida, precioLista, resultado, numMeses, restaurar, nueva, } }