import { Icon } from "@iconify/react";
import {
  Alert, Autocomplete, Box, Button, Chip, CircularProgress, Paper, Stack, TextField, ToggleButton, ToggleButtonGroup,
  Typography,
} from "@mui/material";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import PropTypes from "prop-types";
import { useEffect, useRef, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { toast } from "sonner";
import {
  crearCotizacionInm, getParametrosInm, getPlanesInm, getProyectosInm, getUnidadesInm, getUnidadInm,
} from "../../api/inmobiliario.service";
import { EmptyState, FieldHint, InlineValidationBanner, ScreenGuia } from "../../components/_standards";
import { chipDe, INM_UNIDAD_ESTADOS, INM_UNIDAD_TIPOS } from "../../components/_standards/enums/inmobiliario";
import { fmtMoneda } from "../../components/_standards/enums/monedas";
import { ClienteErpAutocomplete } from "../../components/organismos/inmobiliario/cotizaciones/ClienteErpAutocomplete";
import { monedaDe, pasaElTope, sinKey, ubicacionUnidad } from "../../components/organismos/inmobiliario/cotizaciones/cotizacionUtils";
import { OpcionPlanForm } from "../../components/organismos/inmobiliario/cotizaciones/OpcionPlanForm";
import { comoLista } from "../../components/organismos/inmobiliario/inmUtils";
import { usePermission } from "../../hooks/usePermission";

const GUIA_PASOS = [
  {
    icon: "mdi:home-search-outline",
    color: "#60a5fa",
    titulo: "1. Elegí la unidad",
    desc: "Sólo se cotizan unidades disponibles. El precio de lista y la moneda salen de la unidad.",
  },
  {
    icon: "mdi:account-outline",
    color: "#fbbf24",
    titulo: "2. Cargá el interesado",
    desc: "Si ya es cliente, buscalo. Si no, alcanza con el nombre: para reservar sí tiene que estar cargado como cliente.",
  },
  {
    icon: "mdi:scale-balance",
    color: "#34d399",
    titulo: "3. Compará hasta tres planes",
    desc: "Cada opción es un plan del proyecto con su descuento. El cronograma es estimado desde hoy: las fechas reales se fijan al firmar el boleto.",
  },
];

const GUIA_NOTAS = [
  { icon: "mdi:percent-outline", text: "Un descuento por encima del tope de los parámetros necesita el permiso de autorizar descuentos." },
  { icon: "mdi:cash-lock", text: "Cada plan tiene que tener una seña de al menos el mínimo configurado: la reserva se hace con esa seña." },
];

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function Seccion({ icon, titulo, extra, children }) {
  return (
    <Paper variant="outlined" sx={{ p: 2, bgcolor: "action.hover", borderRadius: 1.5 }}>
      <Box sx={{ display: "flex", alignItems: "center", gap: 1, mb: 1.5, flexWrap: "wrap" }}>
        <Icon icon={icon} width={18} />
        <Typography variant="caption" fontWeight={700} sx={{ letterSpacing: 0.5, color: "text.secondary", textTransform: "uppercase" }}>
          {titulo}
        </Typography>
        {extra && <Box sx={{ ml: "auto" }}>{extra}</Box>}
      </Box>
      {children}
    </Paper>
  );
}

Seccion.propTypes = { icon: PropTypes.string.isRequired, titulo: PropTypes.string.isRequired, extra: PropTypes.node, children: PropTypes.node };

const GRILLA = {
  display: "grid",
  gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 240px), 1fr))",
  gap: 1.5,
  alignItems: "start",
};

const etiquetaUnidad = (u) => {
  if (!u) return "";
  const tipo = chipDe(INM_UNIDAD_TIPOS, u.tipo).label;
  return [u.codigo, tipo, ubicacionUnidad(u)].filter(Boolean).join(" · ");
};

export function InmCotizacionNueva() {
  const { can } = usePermission("INMOBILIARIO");
  const canCreate = can("INM_COT_COTIZACION_CREAR");
  const puedeAutorizar = can("INM_COT_DESCUENTO_AUTORIZAR");

  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const [searchParams] = useSearchParams();
  const unidadIdUrl = searchParams.get("unidad_id");

  const contador = useRef(1);
  const nuevaOpcion = (plan_id = "") => ({ key: `op-${contador.current++}`, plan_id, descuento_pct: 0 });

  const [proyecto, setProyecto] = useState(null);
  const [unidad, setUnidad] = useState(null);
  const [modo, setModo] = useState("cliente");
  const [cliente, setCliente] = useState(null);
  const [prospecto, setProspecto] = useState({ nombre: "", telefono: "", email: "" });
  const [opciones, setOpciones] = useState(() => [nuevaOpcion()]);
  const [notas, setNotas] = useState("");
  const [errores, setErrores] = useState([]);
  const [guardando, setGuardando] = useState(false);
  const [avisoUrl, setAvisoUrl] = useState("");
  const precargada = useRef(false);
  const bannerRef = useRef(null);

  const base = { enabled: canCreate, refetchOnWindowFocus: false };

  const { data: proyectosResp, isLoading: cargandoProyectos } = useQuery({
    queryKey: ["inmobiliario", "proyectos", {}],
    queryFn: () => getProyectosInm(),
    ...base,
  });
  const proyectos = comoLista(proyectosResp);

  const { data: parametros } = useQuery({
    queryKey: ["inmobiliario", "parametros"],
    queryFn: getParametrosInm,
    ...base,
    retry: false,
    staleTime: 5 * 60_000,
  });
  const tope = parametros ? Number(parametros.pct_descuento_max) : null;
  const pctSenaMin = parametros ? Number(parametros.pct_sena_min) : null;

  const { data: unidadUrl, isError: unidadUrlError } = useQuery({
    queryKey: ["inmobiliario", "unidad", unidadIdUrl],
    queryFn: () => getUnidadInm(unidadIdUrl),
    ...base,
    enabled: canCreate && Boolean(unidadIdUrl),
    retry: false,
  });

  const { data: unidadesResp, isLoading: cargandoUnidades } = useQuery({
    queryKey: ["inmobiliario", "unidades", { proyecto_id: proyecto?.id, estado: "DISPONIBLE" }],
    queryFn: () => getUnidadesInm({ proyecto_id: proyecto.id, estado: "DISPONIBLE" }),
    ...base,
    enabled: canCreate && Boolean(proyecto?.id),
  });
  const unidades = comoLista(unidadesResp);

  const { data: planesResp, isLoading: cargandoPlanes } = useQuery({
    queryKey: ["inmobiliario", "planes", proyecto?.id],
    queryFn: () => getPlanesInm(proyecto.id),
    ...base,
    enabled: canCreate && Boolean(proyecto?.id),
  });
  const planes = comoLista(planesResp);

  // Deep-link desde la unidad: precarga proyecto y unidad una sola vez.
  useEffect(() => {
    if (precargada.current) return;
    if (unidadUrlError) {
      precargada.current = true;
      setAvisoUrl("No encontramos la unidad del enlace. Elegila de la lista.");
      return;
    }
    if (!unidadUrl) return;
    precargada.current = true;
    setProyecto(unidadUrl.inm_proyectos ?? null);
    if (unidadUrl.estado === "DISPONIBLE") setUnidad(unidadUrl);
    else
      setAvisoUrl(
        `La unidad ${unidadUrl.codigo} está ${chipDe(INM_UNIDAD_ESTADOS, unidadUrl.estado).label.toLowerCase()}: sólo se cotizan unidades disponibles.`,
      );
  }, [unidadUrl, unidadUrlError]);

  // Con los planes del proyecto cargados, la primera opción arranca con el primero.
  useEffect(() => {
    if (!planes.length) return;
    setOpciones((ops) => {
      if (ops.some((o) => o.plan_id && planes.some((p) => p.id === o.plan_id))) return ops;
      return ops.map((o, i) => (i === 0 ? { ...o, plan_id: planes[0].id } : { ...o, plan_id: "" }));
    });
  }, [planesResp]); // eslint-disable-line react-hooks/exhaustive-deps

  if (!canCreate) return null;

  const moneda = monedaDe(unidad);
  const precioLista = Number(unidad?.precio_lista ?? 0);

  const cambiarProyecto = (p) => {
    setProyecto(p);
    setUnidad(null);
    setOpciones([nuevaOpcion()]);
    setErrores([]);
  };

  const actualizarOpcion = (i) => (op) => setOpciones((ops) => ops.map((o, j) => (j === i ? op : o)));
  const quitarOpcion = (i) => () => setOpciones((ops) => ops.filter((_, j) => j !== i));
  const agregarOpcion = () => {
    const libre = planes.find((p) => !opciones.some((o) => o.plan_id === p.id));
    setOpciones((ops) => [...ops, nuevaOpcion(libre?.id ?? "")]);
  };

  // Motivos por los que todavía no se puede guardar (el primero se muestra junto al botón).
  const bloqueos = [];
  if (!unidad) bloqueos.push("Elegí la unidad a cotizar");
  if (modo === "cliente" && !cliente) bloqueos.push("Elegí el cliente");
  if (modo === "prospecto" && !prospecto.nombre.trim()) bloqueos.push("Cargá el nombre del interesado");
  if (modo === "prospecto" && prospecto.email.trim() && !EMAIL_RE.test(prospecto.email.trim()))
    bloqueos.push("El email del interesado no es válido");
  opciones.forEach((o, i) => {
    const d = Number(o.descuento_pct);
    if (!o.plan_id) bloqueos.push(`Opción ${i + 1}: elegí el plan de pago`);
    if (o.descuento_pct === "" || Number.isNaN(d) || d < 0 || d > 100)
      bloqueos.push(`Opción ${i + 1}: el descuento va de 0 a 100 %`);
    else if (pasaElTope(d, tope) && !puedeAutorizar)
      bloqueos.push(`Opción ${i + 1}: pasa el tope de ${tope} %: necesita autorización`);
  });

  const handleGuardar = async () => {
    if (bloqueos.length) return;
    const payload = {
      unidad_id: unidad.id,
      ...(modo === "cliente"
        ? { cliente_id: cliente.id }
        : {
            prospecto_nombre: prospecto.nombre.trim(),
            prospecto_telefono: prospecto.telefono.trim() || undefined,
            prospecto_email: prospecto.email.trim() || undefined,
          }),
      notas: notas.trim() || undefined,
      opciones: opciones.map((o) => ({ plan_id: o.plan_id, descuento_pct: Number(o.descuento_pct) || 0 })),
    };
    setGuardando(true);
    setErrores([]);
    try {
      const r = await crearCotizacionInm(payload);
      toast.success(`Cotización ${r.numero} creada`);
      queryClient.invalidateQueries({ queryKey: ["inmobiliario", "cotizaciones"] });
      navigate(`/inmobiliario/cotizaciones/${r.id}`);
    } catch (e) {
      const m = e?.response?.data?.message;
      setErrores(Array.isArray(m) ? m : [m || "No se pudo guardar la cotización"]);
      setTimeout(() => bannerRef.current?.scrollIntoView({ behavior: "smooth", block: "center" }), 50);
    } finally {
      setGuardando(false);
    }
  };

  return (
    <Box sx={{ p: { xs: 2, md: 3 }, pb: 0 }}>
      <Stack spacing={2}>
        <Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap" useFlexGap>
          <Button size="small" startIcon={<Icon icon="mdi:arrow-left" />} onClick={() => navigate("/inmobiliario/cotizaciones")}>
            Volver
          </Button>
          <Typography variant="h6" fontWeight={700}>
            Nueva cotización
          </Typography>
        </Stack>

        <ScreenGuia
          moduloPadre="Inmobiliario"
          intro="Armá una propuesta para una unidad comparando hasta tres planes de pago. Desde la cotización se hace la reserva."
          pasos={GUIA_PASOS}
          notas={GUIA_NOTAS}
        />

        <Seccion
          icon="mdi:home-city-outline"
          titulo="Unidad"
          extra={unidad ? <Chip size="small" color="success" variant="outlined" label="Disponible" /> : null}
        >
          {avisoUrl && (
            <Alert severity="warning" sx={{ mb: 1.5 }} onClose={() => setAvisoUrl("")}>
              {avisoUrl}
            </Alert>
          )}
          <Box sx={GRILLA}>
            <Autocomplete
              fullWidth
              options={proyectos}
              value={proyecto}
              loading={cargandoProyectos}
              onChange={(_, p) => cambiarProyecto(p)}
              getOptionLabel={(p) => (p ? `${p.nombre}${p.codigo ? ` (${p.codigo})` : ""}` : "")}
              isOptionEqualToValue={(o, v) => o.id === v?.id}
              noOptionsText="No hay proyectos"
              renderInput={(params) => (
                <TextField {...params} size="small" label="Proyecto" required placeholder="Buscar proyecto…" />
              )}
            />
            <Autocomplete
              fullWidth
              options={unidades}
              value={unidad}
              loading={cargandoUnidades}
              disabled={!proyecto}
              onChange={(_, u) => {
                setUnidad(u);
                setErrores([]);
              }}
              getOptionLabel={etiquetaUnidad}
              getOptionDisabled={(u) => !(Number(u.precio_lista) > 0)}
              isOptionEqualToValue={(o, v) => o.id === v?.id}
              noOptionsText={proyecto ? "No hay unidades disponibles en este proyecto" : "Elegí primero el proyecto"}
              renderOption={(props, u) => {
                const conPrecio = Number(u.precio_lista) > 0;
                return (
                  <Box component="li" key={u.id} {...sinKey(props)}>
                    <Box sx={{ display: "flex", justifyContent: "space-between", gap: 1, width: "100%" }}>
                      <Box sx={{ minWidth: 0 }}>
                        <Typography variant="body2" fontWeight={600}>
                          {u.codigo}
                        </Typography>
                        <Typography variant="caption" color="text.secondary">
                          {[chipDe(INM_UNIDAD_TIPOS, u.tipo).label, ubicacionUnidad(u), u.tipologia].filter(Boolean).join(" · ")}
                        </Typography>
                      </Box>
                      <Typography variant="body2" sx={{ whiteSpace: "nowrap" }}>
                        {conPrecio ? fmtMoneda(u.precio_lista, monedaDe(u)) : "Sin precio"}
                      </Typography>
                    </Box>
                  </Box>
                );
              }}
              renderInput={(params) => (
                <TextField
                  {...params}
                  size="small"
                  label="Unidad"
                  required
                  placeholder="Ej: A-1203"
                  helperText="Sólo unidades disponibles y con precio de lista"
                />
              )}
            />
          </Box>

          {unidad && (
            <Box
              sx={{
                mt: 1.5,
                display: "grid",
                gridTemplateColumns: "repeat(auto-fill, minmax(min(100%, 150px), 1fr))",
                gap: 1.5,
                p: 1.5,
                borderRadius: 1.5,
                bgcolor: "background.paper",
                border: 1,
                borderColor: "divider",
              }}
            >
              <Box>
                <Typography variant="caption" color="text.secondary">
                  Precio de lista
                </Typography>
                <Typography variant="subtitle1" fontWeight={700}>
                  {fmtMoneda(precioLista, moneda)}
                </Typography>
              </Box>
              <Box>
                <Typography variant="caption" color="text.secondary">
                  Tipo
                </Typography>
                <Stack direction="row" spacing={0.75} alignItems="center">
                  <Icon icon={chipDe(INM_UNIDAD_TIPOS, unidad.tipo).icon ?? "mdi:home-outline"} width={18} />
                  <Typography variant="body2">{chipDe(INM_UNIDAD_TIPOS, unidad.tipo).label}</Typography>
                </Stack>
              </Box>
              <Box>
                <Typography variant="caption" color="text.secondary">
                  Ubicación
                </Typography>
                <Typography variant="body2">{ubicacionUnidad(unidad) || "—"}</Typography>
              </Box>
              {(unidad.tipologia || unidad.m2_propios) && (
                <Box>
                  <Typography variant="caption" color="text.secondary">
                    Tipología / superficie
                  </Typography>
                  <Typography variant="body2">
                    {[unidad.tipologia, unidad.m2_propios ? `${Number(unidad.m2_propios)} m²` : null].filter(Boolean).join(" · ")}
                  </Typography>
                </Box>
              )}
            </Box>
          )}
        </Seccion>

        <Seccion icon="mdi:account-outline" titulo="Interesado">
          <ToggleButtonGroup
            exclusive
            size="small"
            value={modo}
            onChange={(_, v) => v && setModo(v)}
            aria-label="Tipo de interesado"
            sx={{ mb: 1.5, flexWrap: "wrap" }}
          >
            <ToggleButton value="cliente">
              <Icon icon="mdi:account-check-outline" width={18} style={{ marginRight: 6 }} />
              Cliente del ERP
            </ToggleButton>
            <ToggleButton value="prospecto">
              <Icon icon="mdi:account-question-outline" width={18} style={{ marginRight: 6 }} />
              Todavía no es cliente
            </ToggleButton>
          </ToggleButtonGroup>

          {modo === "cliente" ? (
            <Box sx={{ maxWidth: 520 }}>
              <ClienteErpAutocomplete
                value={cliente}
                onChange={setCliente}
                required
                helperText="Buscalo por razón social, RUC o CI"
              />
            </Box>
          ) : (
            <Box sx={GRILLA}>
              <FieldHint
                label="Nombre"
                required
                value={prospecto.nombre}
                onChange={(ev) => setProspecto((p) => ({ ...p, nombre: ev.target.value }))}
                hint="Ej: María Benítez"
                inputProps={{ maxLength: 150 }}
              />
              <FieldHint
                label="Teléfono"
                value={prospecto.telefono}
                onChange={(ev) => setProspecto((p) => ({ ...p, telefono: ev.target.value }))}
                hint="Ej: 0981 123 456"
                inputProps={{ maxLength: 30, inputMode: "tel" }}
              />
              <FieldHint
                label="Email"
                type="email"
                value={prospecto.email}
                onChange={(ev) => setProspecto((p) => ({ ...p, email: ev.target.value }))}
                hint="Ej: maria@ejemplo.com"
                error={Boolean(prospecto.email.trim()) && !EMAIL_RE.test(prospecto.email.trim())}
                inputProps={{ maxLength: 120 }}
              />
            </Box>
          )}
          {modo === "prospecto" && (
            <Typography variant="caption" color="text.secondary" sx={{ display: "block", mt: 1 }}>
              Para reservar, el interesado tiene que estar cargado como cliente.
            </Typography>
          )}
        </Seccion>

        <Seccion
          icon="mdi:scale-balance"
          titulo={`Planes a comparar (${opciones.length} de 3)`}
          extra={
            unidad && planes.length > 0 && opciones.length < 3 ? (
              <Button size="small" startIcon={<Icon icon="mdi:plus" />} onClick={agregarOpcion}>
                Agregar opción
              </Button>
            ) : null
          }
        >
          {!proyecto ? (
            <Typography variant="body2" color="text.secondary">
              Elegí el proyecto y la unidad para ver sus planes de pago.
            </Typography>
          ) : cargandoPlanes ? (
            <CircularProgress size={20} />
          ) : !planes.length ? (
            <EmptyState
              compact
              icon="mdi:calendar-blank-outline"
              title="Este proyecto no tiene planes de pago"
              description="Los planes (seña, cuotas, refuerzos) se cargan en el proyecto."
              ctaLabel="Ir al proyecto"
              ctaIcon="mdi:arrow-right"
              onCta={() => navigate(`/inmobiliario/proyectos/${proyecto.id}`)}
            />
          ) : !unidad ? (
            <Typography variant="body2" color="text.secondary">
              Elegí la unidad: el cronograma se calcula sobre su precio de lista.
            </Typography>
          ) : (
            <Box
              sx={{
                display: "grid",
                gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 300px), 1fr))",
                gap: 1.5,
                alignItems: "start",
              }}
            >
              {opciones.map((o, i) => (
                <OpcionPlanForm
                  key={o.key}
                  indice={i}
                  opcion={o}
                  planes={planes}
                  precioLista={precioLista}
                  moneda={moneda}
                  tope={tope}
                  puedeAutorizar={puedeAutorizar}
                  pctSenaMin={pctSenaMin}
                  onChange={actualizarOpcion(i)}
                  onQuitar={opciones.length > 1 ? quitarOpcion(i) : undefined}
                />
              ))}
            </Box>
          )}
        </Seccion>

        <Seccion icon="mdi:note-text-outline" titulo="Notas">
          <FieldHint
            fullWidth
            multiline
            minRows={2}
            label="Notas (opcional)"
            value={notas}
            onChange={(ev) => setNotas(ev.target.value)}
            hint="Ej: le interesa la cochera del subsuelo; vuelve a llamar el lunes"
            inputProps={{ maxLength: 2000 }}
          />
        </Seccion>

        <Box ref={bannerRef}>
          <InlineValidationBanner errors={errores} title="No se pudo guardar la cotización" />
        </Box>
      </Stack>

      <Box
        sx={{
          position: "sticky",
          bottom: 0,
          mt: 2,
          mx: { xs: -2, md: -3 },
          px: { xs: 2, md: 3 },
          py: 1.5,
          bgcolor: "background.paper",
          borderTop: 1,
          borderColor: "divider",
          boxShadow: "0 -4px 12px rgba(0,0,0,0.06)",
          display: "flex",
          alignItems: "center",
          gap: 1.5,
          flexWrap: "wrap",
          zIndex: 2,
        }}
      >
        {bloqueos.length > 0 && (
          <Stack direction="row" spacing={0.75} alignItems="center" sx={{ minWidth: 0, flex: "1 1 220px" }}>
            <Icon icon="mdi:information-outline" width={18} style={{ flexShrink: 0, opacity: 0.7 }} />
            <Typography variant="body2" color="text.secondary">
              {bloqueos[0]}
              {bloqueos.length > 1 ? ` (y ${bloqueos.length - 1} más)` : ""}
            </Typography>
          </Stack>
        )}
        <Box sx={{ flex: bloqueos.length ? "0 0 auto" : 1 }} />
        <Button onClick={() => navigate("/inmobiliario/cotizaciones")} disabled={guardando}>
          Cancelar
        </Button>
        <Button
          variant="contained"
          startIcon={guardando ? <CircularProgress size={16} color="inherit" /> : <Icon icon="mdi:content-save-outline" />}
          disabled={guardando || bloqueos.length > 0}
          onClick={handleGuardar}
        >
          Guardar cotización
        </Button>
      </Box>
    </Box>
  );
}

export default InmCotizacionNueva;
