import React, { useState, useEffect, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import {
  Box, Typography, Button, Paper, CircularProgress, Alert
} from '@mui/material';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import SaveIcon from '@mui/icons-material/Save';
import perfilService from '../../services/Usuarios/perfilService';
import type { PermisoAsignadoDto } from '../../models/dtos/Usuarios/PermisoAsignadoDto';
import type { PerfilDto } from '../../models/dtos/Usuarios/PerfilDto';
import { usePermissions as usePagePermissions } from '../../hooks/usePermissions';
import axios from 'axios';
import PermisosChecklist from '../../components/Modals/Usuarios/PermisosChecklist';

const SECCION_PERMISSIONS_PREFIX = "SS";

// Permisos exclusivos de SuperAdmin: no se asignan a perfiles ni se muestran en la UI de asignación.
// CS002 = Ajuste manual de saldo (legacy, ya existía en gral_Permisos antes del filtro).
// La reapertura de cierres también es exclusiva SuperAdmin pero no se insertó en gral_Permisos
// porque sería ruido — el backend valida directamente con User.IsInRole('SuperAdmin').
const PERMISOS_SOLO_SUPERADMIN: ReadonlySet<string> = new Set(["CS002"]);

const getModuloFromSeccionCodAcc = (codAcc: string): string | null => {
  if (codAcc === "SS001") return "Distribución";  
  if (codAcc === "SS007") return "Suscripciones"; 
  if (codAcc === "SS002") return "Contables";
  if (codAcc === "SS003") return "Impresión";
  if (codAcc === "SS004") return "Reportes";
  if (codAcc === "SS006") return "Usuarios"; 
  if (codAcc === "SS005") return "Radios";
  return null;
};

const getModuloConceptualDelPermiso = (permisoModulo: string): string => {
  const moduloLower = permisoModulo.toLowerCase();
  if (moduloLower.includes("distribuidores") ||
    moduloLower.includes("canillas") ||
    moduloLower.includes("publicaciones distribución") ||
    moduloLower.includes("zonas distribuidores") ||
    moduloLower.includes("movimientos distribuidores") ||
    moduloLower.includes("empresas") ||
    moduloLower.includes("otros destinos") ||
    moduloLower.includes("ctrl. devoluciones") ||
    moduloLower.includes("movimientos canillas") ||
    moduloLower.includes("salidas otros destinos")) {
    return "Distribución";
  }  
  if (moduloLower.includes("suscripciones")) {
    return "Suscripciones";
  }
  if (moduloLower.includes("cuentas pagos") ||
    moduloLower.includes("cuentas notas") ||
    moduloLower.includes("cuentas tipos pagos") ||
    moduloLower.includes("cuentas cierres")) {
    return "Contables";
  }
  if (moduloLower.includes("impresión tiradas") ||
    moduloLower.includes("impresión bobinas") ||
    moduloLower.includes("impresión plantas") ||
    moduloLower.includes("estados bobinas") ||
    moduloLower.includes("tipos bobinas")) {
    return "Impresión";
  }
  if (moduloLower.includes("usuarios") ||
    moduloLower.includes("perfiles")) {
    return "Usuarios";
  }
  if (moduloLower.includes("reportes")) {
    return "Reportes";
  }
  if (moduloLower.includes("permisos")) {
    return "Permisos (Definición)";
  }  
  if (moduloLower.includes("radios")) {
    return "Radios";
  }
  return permisoModulo;
};

const AsignarPermisosAPerfilPage: React.FC = () => {
  const { idPerfil } = useParams<{ idPerfil: string }>();
  const navigate = useNavigate();
  const { tienePermiso: tienePermisoPagina, isSuperAdmin } = usePagePermissions();

  const puedeAsignar = isSuperAdmin || tienePermisoPagina("PU004");

  const [perfil, setPerfil] = useState<PerfilDto | null>(null);
  const [permisosDisponibles, setPermisosDisponibles] = useState<PermisoAsignadoDto[]>([]);
  const [permisosSeleccionados, setPermisosSeleccionados] = useState<Set<number>>(new Set());
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);

  const idPerfilNum = Number(idPerfil);

  const cargarDatos = useCallback(async () => {
    if (!puedeAsignar) {
      setError("Acceso denegado. No tiene permiso para asignar permisos.");
      setLoading(false);
      return;
    }
    if (isNaN(idPerfilNum)) {
      setError("ID de Perfil inválido.");
      setLoading(false);
      return;
    }
    setLoading(true); setError(null); setSuccessMessage(null);
    try {
      const [perfilData, permisosData] = await Promise.all([
        perfilService.getPerfilById(idPerfilNum),
        perfilService.getPermisosPorPerfil(idPerfilNum) // Esto devuelve todos los permisos con su estado 'asignado'
      ]);
      // Filtrar permisos exclusivos de SuperAdmin (CS002, CC002) para que no aparezcan asignables.
      // No se altera la asignación existente en la DB — solo se ocultan de esta UI.
      const permisosVisibles = permisosData.filter(p => !PERMISOS_SOLO_SUPERADMIN.has(p.codAcc));
      setPerfil(perfilData);
      setPermisosDisponibles(permisosVisibles);
      setPermisosSeleccionados(new Set(permisosVisibles.filter(p => p.asignado).map(p => p.id)));
    } catch (err) {
      console.error(err);
      setError('Error al cargar datos del perfil o permisos.');
      if (axios.isAxiosError(err) && err.response?.status === 404) {
        setError(`Perfil con ID ${idPerfilNum} no encontrado.`);
      }
    } finally {
      setLoading(false);
    }
  }, [idPerfilNum, puedeAsignar]);

  useEffect(() => {
    cargarDatos();
  }, [cargarDatos]);

  const handlePermisoChange = useCallback((
    permisoId: number,
    asignadoViaCheckboxHijo: boolean, // Este valor es el 'e.target.checked' si el clic fue en un hijo
    esPermisoSeccionClick = false,
    moduloConceptualAsociado?: string // Este es el módulo conceptual del padre SSxxx o del grupo del hijo
  ) => {
    setPermisosSeleccionados(prevSelected => {
      const newSelected = new Set(prevSelected);
      const permisoActual = permisosDisponibles.find(p => p.id === permisoId);
      if (!permisoActual) return prevSelected;

      const permisosDelModuloHijo = moduloConceptualAsociado
        ? permisosDisponibles.filter(p => {
          const mc = getModuloConceptualDelPermiso(p.modulo); // Usar la función helper
          return mc === moduloConceptualAsociado && !p.codAcc.startsWith(SECCION_PERMISSIONS_PREFIX);
        })
        : [];

      if (esPermisoSeccionClick && moduloConceptualAsociado) {
        const idPermisoSeccion = permisoActual.id;
        const estabaSeccionSeleccionada = prevSelected.has(idPermisoSeccion);
        const todosHijosEstabanSeleccionados = permisosDelModuloHijo.length > 0 && permisosDelModuloHijo.every(p => prevSelected.has(p.id));
        const ningunHijoEstabaSeleccionado = permisosDelModuloHijo.every(p => !prevSelected.has(p.id));


        if (!estabaSeccionSeleccionada) { // Estaba Off, pasa a "Solo Sección" (Indeterminate si hay hijos)
          newSelected.add(idPermisoSeccion);
          // NO se marcan los hijos
        } else if (estabaSeccionSeleccionada && (ningunHijoEstabaSeleccionado || !todosHijosEstabanSeleccionados) && permisosDelModuloHijo.length > 0) {
          // Estaba "Solo Sección" o "Parcial Hijos", pasa a "Sección + Todos los Hijos"
          newSelected.add(idPermisoSeccion); // Asegurar
          permisosDelModuloHijo.forEach(p => newSelected.add(p.id));
        } else { // Estaba "Sección + Todos los Hijos" (o no había hijos), pasa a Off
          newSelected.delete(idPermisoSeccion);
          permisosDelModuloHijo.forEach(p => newSelected.delete(p.id));
        }

      } else if (!esPermisoSeccionClick && moduloConceptualAsociado) { // Clic en un permiso hijo
        if (asignadoViaCheckboxHijo) {
          newSelected.add(permisoId);
          const permisoSeccionPadre = permisosDisponibles.find(
            ps => ps.codAcc.startsWith(SECCION_PERMISSIONS_PREFIX) && getModuloFromSeccionCodAcc(ps.codAcc) === moduloConceptualAsociado
          );
          if (permisoSeccionPadre && !newSelected.has(permisoSeccionPadre.id)) {
            newSelected.add(permisoSeccionPadre.id); // Marcar padre si no estaba
          }
        } else { // Desmarcando un hijo
          newSelected.delete(permisoId);
          const permisoSeccionPadre = permisosDisponibles.find(
            ps => ps.codAcc.startsWith(SECCION_PERMISSIONS_PREFIX) && getModuloFromSeccionCodAcc(ps.codAcc) === moduloConceptualAsociado
          );
          if (permisoSeccionPadre) {
            const algunOtroHijoSeleccionado = permisosDelModuloHijo.some(p => p.id !== permisoId && newSelected.has(p.id));
            if (!algunOtroHijoSeleccionado && newSelected.has(permisoSeccionPadre.id)) {
              // Si era el último hijo y el padre estaba marcado, NO desmarcamos el padre automáticamente.
              // El estado indeterminate se encargará visualmente.
              // Si quisiéramos que se desmarque el padre, aquí iría: newSelected.delete(permisoSeccionPadre.id);
            }
          }
        }
      } else { // Permiso sin módulo conceptual asociado (ej: "Permisos (Definición)")
        if (asignadoViaCheckboxHijo) {
          newSelected.add(permisoId);
        } else {
          newSelected.delete(permisoId);
        }
      }

      if (successMessage) setSuccessMessage(null);
      if (error) setError(null);
      return newSelected;
    });
  }, [permisosDisponibles, successMessage, error]);


  const handleGuardarCambios = async () => {
    if (!puedeAsignar || !perfil) return;
    setSaving(true); setError(null); setSuccessMessage(null);
    try {
      await perfilService.updatePermisosPorPerfil(perfil.id, {
        permisosIds: Array.from(permisosSeleccionados)
      });
      setSuccessMessage('Permisos actualizados correctamente.');
      await cargarDatos();
    } catch (err: any) {
      console.error(err);
      const message = axios.isAxiosError(err) && err.response?.data?.message
        ? err.response.data.message
        : 'Error al guardar los permisos.';
      setError(message);
    } finally {
      setSaving(false);
    }
  };

  if (loading) {
    return <Box sx={{ display: 'flex', justifyContent: 'center', p: 3 }}><CircularProgress /></Box>;
  }

  if (error && !perfil) {
    return <Alert severity="error" sx={{ m: 2 }}>{error}</Alert>;
  }
  if (!puedeAsignar) {
    return <Alert severity="error" sx={{ m: 2 }}>Acceso denegado.</Alert>;
  }
  if (!perfil && !loading) {
    return <Alert severity="warning" sx={{ m: 2 }}>Perfil no encontrado o error al cargar.</Alert>;
  }

  return (
    <Box sx={{ p: 1 }}>
      <Button startIcon={<ArrowBackIcon />} onClick={() => navigate('/usuarios/perfiles')} sx={{ mb: 2 }}>
        Volver a Perfiles
      </Button>
      <Typography variant="h5" gutterBottom>
        Asignar Permisos al Perfil: {perfil?.nombrePerfil || 'Cargando...'}
      </Typography>
      <Typography variant="body2" color="textSecondary" gutterBottom>
        ID Perfil: {perfil?.id}
      </Typography>

      {error && !successMessage && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
      {successMessage && <Alert severity="success" sx={{ mb: 2 }}>{successMessage}</Alert>}

      <Paper sx={{ p: { xs: 1, sm: 2 }, mt: 2 }}>
        <PermisosChecklist
          permisosDisponibles={permisosDisponibles}
          permisosSeleccionados={permisosSeleccionados}
          onPermisoChange={handlePermisoChange}
          disabled={saving}
        />
        <Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end' }}>
          <Button
            variant="contained"
            color="primary"
            startIcon={saving ? <CircularProgress size={20} color="inherit" /> : <SaveIcon />}
            onClick={handleGuardarCambios}
            disabled={saving || !puedeAsignar}
          >
            Guardar Cambios
          </Button>
        </Box>
      </Paper>
    </Box>
  );
};
export default AsignarPermisosAPerfilPage;