import { create } from 'zustand';
import { progresoService } from '../services/api';
import type { Progreso, Badge, NivelUsuario } from '../types';

export interface EjercicioProgreso {
  ejercicioId: string;
  completado: boolean;
  puntuacion: number;
  fechaCompletado?: string;
  intentos: number;
}

export interface ModuloProgreso {
  moduloId: string;
  ejercicios: Record<string, EjercicioProgreso>;
  completado: boolean;
}

interface ProgressState {
  modulos: Record<string, ModuloProgreso>;
  puntuacionTotal: number;
  badges: Badge[];
  nivel: NivelUsuario;
  isLoading: boolean;
  error: string | null;
  
  // Acciones
  loadProgreso: () => Promise<void>;
  saveProgreso: (moduloId: string, ejercicioId: string, puntuacion: number) => Promise<void>;
  getProgresoEjercicio: (moduloId: string, ejercicioId: string) => EjercicioProgreso | undefined;
  getProgresoModulo: (moduloId: string) => ModuloProgreso | undefined;
  resetProgreso: (moduloId?: string) => void;
  calcularPorcentajeModulo: (moduloId: string, totalEjercicios: number) => number;
  getBadgesDesbloqueados: () => Badge[];
  getBadgesBloqueados: () => Badge[];
  getProgreso: (moduloId: string, ejercicioId: string) => EjercicioProgreso | undefined;
}

function calcularNivel(puntuacion: number): NivelUsuario {
  if (puntuacion >= 2000) return 'Maestro';
  if (puntuacion >= 1000) return 'Experto';
  if (puntuacion >= 300) return 'Aprendiz';
  return 'Novato';
}

function transformarProgresoAPI(progresoAPI: Progreso[]): Record<string, ModuloProgreso> {
  const modulos: Record<string, ModuloProgreso> = {};
  
  progresoAPI.forEach((p) => {
    const moduloId = `modulo${p.modulo_numero}`;
    
    if (!modulos[moduloId]) {
      modulos[moduloId] = {
        moduloId,
        ejercicios: {},
        completado: false,
      };
    }
    
    modulos[moduloId].ejercicios[p.ejercicio_id] = {
      ejercicioId: p.ejercicio_id,
      completado: p.completado,
      puntuacion: p.puntuacion,
      fechaCompletado: new Date().toISOString(),
      intentos: 1,
    };
  });
  
  return modulos;
}

export const useProgressStore = create<ProgressState>()(
  (set, get) => ({
    modulos: {},
    puntuacionTotal: 0,
    badges: [],
    nivel: 'Novato',
    isLoading: false,
    error: null,

    loadProgreso: async () => {
      set({ isLoading: true, error: null });
      
      try {
        const [progresoData, resumenData] = await Promise.all([
          progresoService.getProgreso(),
          progresoService.getResumenProgreso(),
        ]);
        
        const modulos = transformarProgresoAPI(progresoData);
        
        set({
          modulos,
          puntuacionTotal: resumenData?.totalPuntuacion ?? 0,
          badges: resumenData?.badges ?? [],
          nivel: resumenData?.nivel ?? 'Novato',
          isLoading: false,
        });
      } catch (error) {
        set({
          error: error instanceof Error ? error.message : 'Error al cargar el progreso',
          isLoading: false,
        });
        console.error('Error loading progreso:', error);
      }
    },

    saveProgreso: async (moduloId: string, ejercicioId: string, puntuacion: number) => {
      const moduloNumero = parseInt(moduloId.replace('modulo', ''), 10);
      
      set({ isLoading: true, error: null });
      
      try {
        // Guardar en la API
        await progresoService.saveProgreso({
          modulo_numero: moduloNumero,
          ejercicio_id: ejercicioId,
          puntuacion,
          completado: true,
        });
        
        // Actualizar estado local
        set((state) => {
          const modulo = state.modulos[moduloId] || {
            moduloId,
            ejercicios: {},
            completado: false,
          };

          const ejercicioExistente = modulo.ejercicios[ejercicioId];
          const esMejorPuntuacion = !ejercicioExistente || puntuacion > ejercicioExistente.puntuacion;

          const nuevoEjercicio: EjercicioProgreso = {
            ejercicioId,
            completado: true,
            puntuacion: esMejorPuntuacion ? puntuacion : ejercicioExistente.puntuacion,
            fechaCompletado: new Date().toISOString(),
            intentos: (ejercicioExistente?.intentos || 0) + 1,
          };

          const nuevosEjercicios = {
            ...modulo.ejercicios,
            [ejercicioId]: nuevoEjercicio,
          };

          const moduloActualizado: ModuloProgreso = {
            ...modulo,
            ejercicios: nuevosEjercicios,
          };

          // Recalcular puntuación total
          let nuevaPuntuacionTotal = 0;
          Object.values(state.modulos).forEach((mod) => {
            if (mod.moduloId !== moduloId) {
              Object.values(mod.ejercicios).forEach((ej) => {
                if (ej.completado) {
                  nuevaPuntuacionTotal += ej.puntuacion;
                }
              });
            }
          });
          
          // Agregar ejercicios del módulo actual
          Object.values(nuevosEjercicios).forEach((ej) => {
            if (ej.completado) {
              nuevaPuntuacionTotal += ej.puntuacion;
            }
          });

          const nuevoNivel = calcularNivel(nuevaPuntuacionTotal);

          return {
            modulos: {
              ...state.modulos,
              [moduloId]: moduloActualizado,
            },
            puntuacionTotal: nuevaPuntuacionTotal,
            nivel: nuevoNivel,
            isLoading: false,
          };
        });
        
        // Recargar resumen para obtener badges actualizados
        const resumen = await progresoService.getResumenProgreso();
        set({
          badges: resumen?.badges ?? [],
          nivel: resumen?.nivel ?? 'Novato',
        });
      } catch (error) {
        set({
          error: error instanceof Error ? error.message : 'Error al guardar el progreso',
          isLoading: false,
        });
        console.error('Error saving progreso:', error);
        throw error;
      }
    },

    getProgresoEjercicio: (moduloId: string, ejercicioId: string) => {
      const state = get();
      return state.modulos[moduloId]?.ejercicios[ejercicioId];
    },

    getProgresoModulo: (moduloId: string) => {
      const state = get();
      return state.modulos[moduloId];
    },

    resetProgreso: (moduloId?: string) => {
      if (moduloId) {
        set((state) => {
          const { [moduloId]: _, ...restoModulos } = state.modulos;
          
          // Recalcular puntuación
          let nuevaPuntuacionTotal = 0;
          Object.values(restoModulos).forEach((mod) => {
            Object.values(mod.ejercicios).forEach((ej) => {
              if (ej.completado) {
                nuevaPuntuacionTotal += ej.puntuacion;
              }
            });
          });

          return {
            modulos: restoModulos,
            puntuacionTotal: nuevaPuntuacionTotal,
            nivel: calcularNivel(nuevaPuntuacionTotal),
          };
        });
      } else {
        set({
          modulos: {},
          puntuacionTotal: 0,
          nivel: 'Novato',
        });
      }
    },

    calcularPorcentajeModulo: (moduloId: string, totalEjercicios: number): number => {
      const state = get();
      const modulo = state.modulos[moduloId];
      if (!modulo || totalEjercicios === 0) return 0;

      const ejerciciosCompletados = Object.values(modulo.ejercicios).filter(
        (ej) => ej.completado
      ).length;

      // Limitar a máximo 100%
      const porcentaje = Math.round((ejerciciosCompletados / totalEjercicios) * 100);
      return Math.min(porcentaje, 100);
    },

    getBadgesDesbloqueados: () => {
      return get().badges.filter(b => b.desbloqueado);
    },

    getBadgesBloqueados: () => {
      return get().badges.filter(b => !b.desbloqueado);
    },

    getProgreso: (moduloId: string, ejercicioId: string) => {
      const state = get();
      return state.modulos[moduloId]?.ejercicios[ejercicioId];
    },
  })
);

export default useProgressStore;
