import { Box, Stack } from "@mui/material";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useMemo, useState } from "react";
import { toast } from "sonner";
import {
  actualizarEtapa, actualizarPipeline, crearEtapa, crearPipeline,
  darDeBajaEtapa, darDeBajaPipeline, getPipelines, reordenarEtapas,
} from "../../api/crm-config.service";
import { ScreenGuia } from "../../components/_standards";
import { EtapaFormDialog } from "../../components/organismos/crm/EtapaFormDialog";
import { PipelineFormDialog } from "../../components/organismos/crm/PipelineFormDialog";
import { CrmConfigTemplate } from "../../components/templates/crm/CrmConfigTemplate";
import { useConfirmDialog } from "../../hooks/useConfirmDialog";
import { usePermission } from "../../hooks/usePermission";
import { useCrmStore } from "../../store/crmStore";

const GUIA_PASOS = [
  {
    icon: "mdi:filter-variant",
    color: "#60a5fa",
    titulo: "1. Un embudo por forma de vender",
    desc: "Si vendés en mostrador y a mayoristas con procesos distintos, hacé un embudo para cada uno. Si no, alcanza con el que viene.",
  },
  {
    icon: "mdi:format-list-numbered",
    color: "#34d399",
    titulo: "2. Ordená las etapas como vende tu equipo",
    desc: "El orden es el que va a ver el vendedor en el tablero. Se cambia con las flechas.",
  },
  {
    icon: "mdi:clipboard-check-outline",
    color: "#fbbf24",
    titulo: "3. Pedí los datos en el momento justo",
    desc: "Los campos obligatorios de una etapa se exigen al entrar. Así la factura sale bien a la primera, sin frenar al vendedor antes de tiempo.",
  },
  {
    icon: "mdi:timer-sand",
    color: "#f87171",
    titulo: "4. Marcá cuándo una oportunidad se enfrió",
    desc: "Con los días de estancamiento, la tarjeta se pone en rojo y el vendedor recibe el aviso.",
  },
];

const GUIA_NOTAS = [
  { text: "Cada embudo necesita una etapa de cierre ganado y una de cierre perdido, y sólo una de cada una." },
  { text: "Mover una oportunidad a la etapa ganada exige pasar por el asistente de cierre: no se puede arrastrar." },
  { text: "Nada se borra. Dar de baja un embudo o una etapa los deja inactivos, porque las oportunidades que pasaron por ahí los siguen referenciando." },
];

export function CrmConfig() {
  const { can } = usePermission("CRM");
  const canRead = can("CRM_CFG_PIPELINE_VER");
  const canCreate = can("CRM_CFG_PIPELINE_CREAR");
  const canEdit = can("CRM_CFG_PIPELINE_EDITAR");
  const canDelete = can("CRM_CFG_PIPELINE_ELIMINAR");

  const queryClient = useQueryClient();
  const { confirm, dialogs } = useConfirmDialog();
  const { pipelineId, setPipelineId } = useCrmStore();

  const [pipelineForm, setPipelineForm] = useState({ open: false, pipeline: null });
  const [etapaForm, setEtapaForm] = useState({ open: false, etapa: null });
  const [saving, setSaving] = useState(false);

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

  const pipelineSel = useMemo(
    () => pipelines.find((p) => p.id === pipelineId) ?? pipelines[0] ?? null,
    [pipelines, pipelineId],
  );

  // Al entrar por primera vez el store está vacío: fijamos el primero para que
  // la tabla de la derecha no quede en blanco.
  useEffect(() => {
    if (!pipelineId && pipelineSel) setPipelineId(pipelineSel.id);
  }, [pipelineId, pipelineSel, setPipelineId]);

  const etapas = useMemo(
    () => [...(pipelineSel?.crm_etapas ?? [])].sort((a, b) => a.orden - b.orden),
    [pipelineSel],
  );

  const invalidar = () => queryClient.invalidateQueries({ queryKey: ["crm", "pipelines"] });

  const conError = async (fn, exito) => {
    setSaving(true);
    try {
      await fn();
      toast.success(exito);
      invalidar();
      return true;
    } catch (e) {
      toast.error(e?.response?.data?.message || "No se pudo guardar");
      return false;
    } finally {
      setSaving(false);
    }
  };

  const handleSubmitPipeline = async (payload) => {
    const ok = await conError(
      () =>
        pipelineForm.pipeline
          ? actualizarPipeline(pipelineForm.pipeline.id, payload)
          : crearPipeline(payload),
      pipelineForm.pipeline ? "Embudo actualizado" : "Embudo creado",
    );
    if (ok) setPipelineForm({ open: false, pipeline: null });
  };

  const handleSubmitEtapa = async (payload) => {
    const ok = await conError(
      () =>
        etapaForm.etapa
          ? actualizarEtapa(etapaForm.etapa.id, payload)
          : crearEtapa(pipelineSel.id, payload),
      etapaForm.etapa ? "Etapa actualizada" : "Etapa creada",
    );
    if (ok) setEtapaForm({ open: false, etapa: null });
  };

  const handleBajaPipeline = async (p) => {
    const ok = await confirm({
      title: "Dar de baja el embudo",
      message: `"${p.nombre}" deja de ofrecerse para oportunidades nuevas. Las que ya están en él no se tocan. ¿Confirmás?`,
      confirmText: "Dar de baja",
      confirmColor: "error",
    });
    if (ok) await conError(() => darDeBajaPipeline(p.id), "Embudo dado de baja");
  };

  const handleBajaEtapa = async (e) => {
    const ok = await confirm({
      title: "Dar de baja la etapa",
      message: `"${e.nombre}" deja de aparecer en el tablero. Las oportunidades que pasaron por ella la siguen referenciando. ¿Confirmás?`,
      confirmText: "Dar de baja",
      confirmColor: "error",
    });
    if (ok) await conError(() => darDeBajaEtapa(e.id), "Etapa dada de baja");
  };

  /**
   * El backend exige la lista COMPLETA de etapas activas: una parcial deja el
   * tablero mezclado. Por eso se manda el array entero ya reordenado.
   */
  const handleMoverEtapa = async (etapa, delta) => {
    const ids = etapas.map((e) => e.id);
    const i = ids.indexOf(etapa.id);
    const j = i + delta;
    if (j < 0 || j >= ids.length) return;
    [ids[i], ids[j]] = [ids[j], ids[i]];
    await conError(() => reordenarEtapas(pipelineSel.id, ids), "Orden actualizado");
  };

  if (!canRead) return null;

  return (
    <Box sx={{ p: { xs: 2, md: 3 } }}>
      <Stack spacing={2}>
        <ScreenGuia
          moduloPadre="CRM"
          intro="Acá se define cómo vende tu equipo: los embudos, sus etapas y qué datos se piden en cada una."
          pasos={GUIA_PASOS}
          notas={GUIA_NOTAS}
        />

        <CrmConfigTemplate
          pipelines={pipelines}
          pipelineSel={pipelineSel}
          etapas={etapas}
          loading={isLoading}
          canCreate={canCreate}
          canEdit={canEdit}
          canDelete={canDelete}
          onSeleccionarPipeline={(p) => setPipelineId(p.id)}
          onNuevoPipeline={() => setPipelineForm({ open: true, pipeline: null })}
          onEditarPipeline={(p) => setPipelineForm({ open: true, pipeline: p })}
          onBajaPipeline={handleBajaPipeline}
          onNuevaEtapa={() => setEtapaForm({ open: true, etapa: null })}
          onEditarEtapa={(e) => setEtapaForm({ open: true, etapa: e })}
          onBajaEtapa={handleBajaEtapa}
          onMoverEtapa={handleMoverEtapa}
        />
      </Stack>

      <PipelineFormDialog
        open={pipelineForm.open}
        pipeline={pipelineForm.pipeline}
        saving={saving}
        onClose={() => setPipelineForm({ open: false, pipeline: null })}
        onSubmit={handleSubmitPipeline}
      />
      <EtapaFormDialog
        open={etapaForm.open}
        etapa={etapaForm.etapa}
        saving={saving}
        onClose={() => setEtapaForm({ open: false, etapa: null })}
        onSubmit={handleSubmitEtapa}
      />
      {dialogs}
    </Box>
  );
}

export default CrmConfig;
