import { Icon } from "@iconify/react";
import {
  Box, FormControlLabel, MenuItem, Paper, Stack, Switch, TextField,
  ToggleButton, ToggleButtonGroup, Tooltip, Typography,
} from "@mui/material";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { toast } from "sonner";
import { getPipelines } from "../../api/crm-config.service";
import { getKanban, getOportunidades, moverEtapa } from "../../api/crm-oportunidades.service";
import { EmptyState, EstadoChip, ScreenGuia, StandardTable } from "../../components/_standards";
import { KanbanTemplate } from "../../components/templates/crm/KanbanTemplate";
import { usePermission } from "../../hooks/usePermission";
import { useCrmStore } from "../../store/crmStore";
import { etiquetaCampo } from "../../components/organismos/crm/camposOportunidad";

const gs = (n) => new Intl.NumberFormat("es-PY", { maximumFractionDigits: 0 }).format(Number(n) || 0);

const GUIA_PASOS = [
  {
    icon: "mdi:drag-variant",
    color: "#60a5fa",
    titulo: "1. Arrastrá la tarjeta a la etapa que corresponde",
    desc: "En el celular o con el teclado, usá el botón de la flecha en la tarjeta: hace exactamente lo mismo.",
  },
  {
    icon: "mdi:clipboard-alert-outline",
    color: "#fbbf24",
    titulo: "2. Si la etapa pide datos, te los va a pedir",
    desc: "Cada etapa exige tener cargado lo que se definió en Configuración. La tarjeta no se mueve hasta completarlo.",
  },
  {
    icon: "mdi:cash-register",
    color: "#34d399",
    titulo: "3. Para ganar, abrí el asistente de cierre",
    desc: "Ganar emite la orden o la factura, así que no se puede arrastrar hasta Ganada: se hace desde el detalle.",
  },
  {
    icon: "mdi:snowflake",
    color: "#f87171",
    titulo: "4. Las tarjetas en rojo están frías",
    desc: "Llevan más días sin actividad que los que definiste en la etapa. Son las primeras que hay que llamar.",
  },
];

const GUIA_NOTAS = [
  { text: "El total de cada columna muestra también el valor ponderado: lo que se espera cobrar según la probabilidad de la etapa." },
  { text: "Si no tenés permiso para ver las oportunidades de otros vendedores, el tablero muestra sólo las tuyas." },
];

export function CrmTablero() {
  const { can } = usePermission("CRM");
  const canRead = can("CRM_OPO_OPORTUNIDAD_VER");
  const canEdit = can("CRM_OPO_OPORTUNIDAD_EDITAR");

  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { pipelineId, setPipelineId, filtros, setFiltro } = useCrmStore();
  const [vista, setVista] = useState("kanban");

  const { data: pipelines = [] } = useQuery({
    queryKey: ["crm", "pipelines", "activos"],
    queryFn: () => getPipelines(true),
    enabled: canRead,
    refetchOnWindowFocus: false,
  });

  useEffect(() => {
    if (!pipelineId && pipelines.length) setPipelineId(pipelines[0].id);
  }, [pipelineId, pipelines, setPipelineId]);

  const { data: tablero, isLoading } = useQuery({
    queryKey: ["crm", "kanban", pipelineId],
    queryFn: () => getKanban(pipelineId),
    enabled: canRead && Boolean(pipelineId) && vista === "kanban",
    refetchOnWindowFocus: false,
  });

  const { data: lista = [], isLoading: cargandoLista } = useQuery({
    queryKey: ["crm", "oportunidades", pipelineId],
    queryFn: () => getOportunidades({ pipeline_id: pipelineId }),
    enabled: canRead && Boolean(pipelineId) && vista === "lista",
    refetchOnWindowFocus: false,
  });

  const etapas = useMemo(() => (tablero?.columnas ?? []).map((c) => c.etapa), [tablero]);

  /** El filtro es local: el tablero ya trae todo el embudo abierto en una sola llamada. */
  const columnasFiltradas = useMemo(() => {
    const texto = filtros.texto.trim().toLowerCase();
    return (tablero?.columnas ?? []).map((c) => {
      const items = c.oportunidades.filter((o) => {
        if (filtros.soloEstancadas && !o.estancada) return false;
        if (!texto) return true;
        return `${o.titulo} ${o.numero}`.toLowerCase().includes(texto);
      });
      // Los totales se recalculan sobre lo filtrado: dejar el total del backend
      // mientras se ven tres tarjetas de veinte sería mentirle al usuario.
      const total = items.reduce((a, o) => a + Number(o.valor_unico) + Number(o.valor_mrr), 0);
      return {
        ...c,
        oportunidades: items,
        total,
        total_ponderado: Math.round((total * c.etapa.probabilidad) / 100),
      };
    });
  }, [tablero, filtros]);

  const handleMover = async (oportunidad, etapa) => {
    if (!canEdit) return;
    try {
      await moverEtapa(oportunidad.id, etapa.id);
      toast.success(`Movida a ${etapa.nombre}`);
      queryClient.invalidateQueries({ queryKey: ["crm", "kanban"] });
      queryClient.invalidateQueries({ queryKey: ["crm", "oportunidades"] });
    } catch (e) {
      const cuerpo = e?.response?.data ?? {};
      // El backend distingue tres negativas y cada una se resuelve en otro lugar:
      // por eso el mensaje tiene que decir dónde, no sólo que no se pudo.
      if (cuerpo.requiere === "cierre") {
        toast.error("Para ganarla hay que completar el asistente de cierre", {
          action: { label: "Abrir", onClick: () => navigate(`/crm/oportunidades/${oportunidad.id}`) },
        });
      } else if (cuerpo.requiere === "motivo_perdida") {
        toast.error("Para marcarla perdida hace falta el motivo", {
          action: { label: "Abrir", onClick: () => navigate(`/crm/oportunidades/${oportunidad.id}`) },
        });
      } else if (cuerpo.campos_faltantes?.length) {
        toast.error(`Faltan datos para esa etapa: ${cuerpo.campos_faltantes.map(etiquetaCampo).join(", ")}`, {
          action: { label: "Completar", onClick: () => navigate(`/crm/oportunidades/${oportunidad.id}`) },
        });
      } else {
        toast.error(cuerpo.message || "No se pudo mover la oportunidad");
      }
    }
  };

  const columnasLista = [
    { key: "numero", label: "Número", minWidth: 120, render: (r) => r.numero },
    { key: "titulo", label: "Oportunidad", minWidth: 220, primary: true, wrap: true, render: (r) => r.titulo },
    { key: "etapa", label: "Etapa", minWidth: 150, render: (r) => r.crm_etapas?.nombre ?? "—" },
    {
      key: "estado",
      label: "Estado",
      minWidth: 110,
      render: (r) => <EstadoChip estado={r.estado} />,
    },
    { key: "valor", label: "Valor", minWidth: 130, render: (r) => `Gs ${gs(Number(r.valor_unico) + Number(r.valor_mrr))}` },
    { key: "prob", label: "Prob.", minWidth: 80, render: (r) => `${r.probabilidad}%` },
    {
      key: "fria",
      label: "",
      minWidth: 60,
      render: (r) =>
        r.estancada ? (
          <Tooltip title="Sin actividad hace días" enterDelay={300}>
            <Icon icon="mdi:snowflake" color="#f87171" width={18} />
          </Tooltip>
        ) : null,
    },
  ];

  if (!canRead) return null;

  return (
    <Box sx={{ p: { xs: 2, md: 3 } }}>
      <Stack spacing={2}>
        <ScreenGuia
          moduloPadre="CRM"
          intro="El tablero es donde el equipo ve en qué va cada venta y qué hay que empujar hoy."
          pasos={GUIA_PASOS}
          notas={GUIA_NOTAS}
        />

        <Paper variant="outlined" sx={{ p: 1.5 }}>
          <Stack
            direction={{ xs: "column", md: "row" }}
            spacing={1.5}
            alignItems={{ xs: "stretch", md: "center" }}
          >
            <TextField
              select
              size="small"
              label="Embudo"
              value={pipelineId ?? ""}
              onChange={(ev) => setPipelineId(ev.target.value)}
              sx={{ minWidth: 200 }}
            >
              {pipelines.map((p) => (
                <MenuItem key={p.id} value={p.id}>
                  {p.nombre}
                </MenuItem>
              ))}
            </TextField>

            <TextField
              size="small"
              label="Buscar"
              placeholder="Ej: OPP-0000124 o Equipamiento"
              value={filtros.texto}
              onChange={(ev) => setFiltro("texto", ev.target.value)}
              sx={{ minWidth: 220 }}
            />

            <FormControlLabel
              control={
                <Switch
                  size="small"
                  checked={filtros.soloEstancadas}
                  onChange={(ev) => setFiltro("soloEstancadas", ev.target.checked)}
                />
              }
              label="Sólo frías"
            />

            <Box sx={{ flexGrow: 1 }} />

            <ToggleButtonGroup
              size="small"
              exclusive
              value={vista}
              onChange={(_, v) => v && setVista(v)}
              aria-label="Forma de ver las oportunidades"
            >
              <ToggleButton value="kanban" aria-label="Ver como tablero">
                <Icon icon="mdi:view-column-outline" width={18} />
                <Box component="span" sx={{ ml: 0.5, display: { xs: "none", sm: "inline" } }}>
                  Tablero
                </Box>
              </ToggleButton>
              <ToggleButton value="lista" aria-label="Ver como lista">
                <Icon icon="mdi:format-list-bulleted" width={18} />
                <Box component="span" sx={{ ml: 0.5, display: { xs: "none", sm: "inline" } }}>
                  Lista
                </Box>
              </ToggleButton>
            </ToggleButtonGroup>
          </Stack>
        </Paper>

        {!pipelines.length ? (
          <EmptyState
            icon="mdi:filter-variant"
            title="Todavía no hay embudos"
            description="Creá un embudo en Configuración del CRM para empezar a cargar oportunidades."
            ctaLabel="Ir a configuración"
            onCta={() => navigate("/crm/configuracion")}
          />
        ) : vista === "kanban" ? (
          <>
            {tablero && (
              <Typography variant="caption" color="text.secondary">
                {columnasFiltradas.reduce((a, c) => a + c.oportunidades.length, 0)} oportunidades abiertas · Gs{" "}
                {gs(columnasFiltradas.reduce((a, c) => a + c.total, 0))} en juego
              </Typography>
            )}
            <KanbanTemplate
              columnas={columnasFiltradas}
              etapas={etapas}
              loading={isLoading}
              puedeMover={canEdit}
              onMover={handleMover}
              onAbrir={(o) => navigate(`/crm/oportunidades/${o.id}`)}
            />
          </>
        ) : (
          <StandardTable
            tableId="crm-oportunidades"
            data={lista}
            columns={columnasLista}
            loading={cargandoLista}
            density="compact"
            onRowClick={(r) => navigate(`/crm/oportunidades/${r.id}`)}
            search={{ value: filtros.texto, onChange: (v) => setFiltro("texto", v) }}
            emptyState={
              <EmptyState
                icon="mdi:handshake-outline"
                title="Sin oportunidades en este embudo"
                description="Las oportunidades nacen de un lead convertido o se cargan a mano desde el tablero."
              />
            }
          />
        )}
      </Stack>
    </Box>
  );
}

export default CrmTablero;
