'use client';

import { useState, useEffect, useCallback } from 'react';

export interface ModuleProgress {
  moduleId: string;
  progress: number; // 0-100
  timeSpent: number; // in seconds
  isCompleted: boolean;
  completedAt?: Date;
  lastAccessedAt: Date;
  bookmarks: {
    id: string;
    title: string;
    timestamp: number; // video timestamp in seconds
    notes?: string;
    createdAt: Date;
  }[];
  quizScores: {
    quizId: string;
    score: number;
    maxScore: number;
    attempts: number;
    completedAt: Date;
  }[];
  assignmentSubmissions: {
    assignmentId: string;
    submittedAt: Date;
    score?: number;
    feedback?: string;
    status: 'submitted' | 'graded' | 'returned';
  }[];
}

export interface CourseProgress {
  courseId: string;
  overallProgress: number; // 0-100
  totalTimeSpent: number; // in seconds
  modulesProgress: ModuleProgress[];
  startedAt: Date;
  lastAccessedAt: Date;
  completedAt?: Date;
  certificateEarned?: boolean;
}

export interface ProgressStats {
  totalCourses: number;
  completedCourses: number;
  inProgressCourses: number;
  totalTimeSpent: number;
  averageProgress: number;
  streakDays: number;
  lastStudyDate?: Date;
}

interface UseProgressTrackingReturn {
  // Course Progress
  courseProgress: CourseProgress | null;
  updateModuleProgress: (moduleId: string, progress: number) => void;
  completeModule: (moduleId: string) => void;
  addTimeSpent: (moduleId: string, seconds: number) => void;
  
  // Bookmarks
  addBookmark: (moduleId: string, title: string, timestamp: number, notes?: string) => void;
  removeBookmark: (moduleId: string, bookmarkId: string) => void;
  updateBookmark: (moduleId: string, bookmarkId: string, title: string, notes?: string) => void;
  
  // Quiz Progress
  recordQuizScore: (moduleId: string, quizId: string, score: number, maxScore: number) => void;
  
  // Assignment Progress
  submitAssignment: (moduleId: string, assignmentId: string) => void;
  gradeAssignment: (moduleId: string, assignmentId: string, score: number, feedback?: string) => void;
  
  // Statistics
  getProgressStats: () => ProgressStats;
  getCourseCompletion: () => number;
  getModuleProgress: (moduleId: string) => ModuleProgress | null;
  
  // Persistence
  saveProgress: () => void;
  loadProgress: (courseId: string) => void;
  clearProgress: (courseId: string) => void;
  
  // Utilities
  isModuleCompleted: (moduleId: string) => boolean;
  getNextIncompleteModule: () => string | null;
  calculateEstimatedCompletion: () => Date | null;
}

const STORAGE_KEY_PREFIX = 'lms_progress_';
const STATS_STORAGE_KEY = 'lms_progress_stats';

export function useProgressTracking(courseId: string): UseProgressTrackingReturn {
  const [courseProgress, setCourseProgress] = useState<CourseProgress | null>(null);
  const storageKey = `${STORAGE_KEY_PREFIX}${courseId}`;

  // Load progress from localStorage on mount
  useEffect(() => {
    loadProgress(courseId);
  }, [courseId]);

  // Auto-save progress when it changes
  useEffect(() => {
    if (courseProgress) {
      saveProgress();
    }
  }, [courseProgress]);

  const loadProgress = useCallback((courseId: string) => {
    try {
      const saved = localStorage.getItem(storageKey);
      if (saved) {
        const parsed = JSON.parse(saved);
        // Convert date strings back to Date objects
        const progress: CourseProgress = {
          ...parsed,
          startedAt: new Date(parsed.startedAt),
          lastAccessedAt: new Date(parsed.lastAccessedAt),
          completedAt: parsed.completedAt ? new Date(parsed.completedAt) : undefined,
          modulesProgress: parsed.modulesProgress.map((mp: any) => ({
            ...mp,
            lastAccessedAt: new Date(mp.lastAccessedAt),
            completedAt: mp.completedAt ? new Date(mp.completedAt) : undefined,
            bookmarks: mp.bookmarks.map((b: any) => ({
              ...b,
              createdAt: new Date(b.createdAt)
            })),
            quizScores: mp.quizScores.map((q: any) => ({
              ...q,
              completedAt: new Date(q.completedAt)
            })),
            assignmentSubmissions: mp.assignmentSubmissions.map((a: any) => ({
              ...a,
              submittedAt: new Date(a.submittedAt)
            }))
          }))
        };
        setCourseProgress(progress);
      } else {
        // Initialize new progress
        const newProgress: CourseProgress = {
          courseId,
          overallProgress: 0,
          totalTimeSpent: 0,
          modulesProgress: [],
          startedAt: new Date(),
          lastAccessedAt: new Date()
        };
        setCourseProgress(newProgress);
      }
    } catch (error) {
      console.error('Error loading progress:', error);
      // Initialize new progress on error
      const newProgress: CourseProgress = {
        courseId,
        overallProgress: 0,
        totalTimeSpent: 0,
        modulesProgress: [],
        startedAt: new Date(),
        lastAccessedAt: new Date()
      };
      setCourseProgress(newProgress);
    }
  }, [storageKey, courseId]);

  const saveProgress = useCallback(() => {
    if (courseProgress) {
      try {
        localStorage.setItem(storageKey, JSON.stringify(courseProgress));
        updateGlobalStats();
      } catch (error) {
        console.error('Error saving progress:', error);
      }
    }
  }, [courseProgress, storageKey]);

  const updateGlobalStats = useCallback(() => {
    try {
      const existingStats = localStorage.getItem(STATS_STORAGE_KEY);
      const stats: ProgressStats = existingStats ? JSON.parse(existingStats) : {
        totalCourses: 0,
        completedCourses: 0,
        inProgressCourses: 0,
        totalTimeSpent: 0,
        averageProgress: 0,
        streakDays: 0
      };

      // Update last study date
      stats.lastStudyDate = new Date();
      
      // Calculate streak (simplified - in real app, you'd track daily activity)
      const today = new Date();
      const lastStudy = stats.lastStudyDate ? new Date(stats.lastStudyDate) : today;
      const daysDiff = Math.floor((today.getTime() - lastStudy.getTime()) / (1000 * 60 * 60 * 24));
      
      if (daysDiff <= 1) {
        stats.streakDays = Math.max(1, stats.streakDays + (daysDiff === 1 ? 1 : 0));
      } else {
        stats.streakDays = 1;
      }

      localStorage.setItem(STATS_STORAGE_KEY, JSON.stringify(stats));
    } catch (error) {
      console.error('Error updating global stats:', error);
    }
  }, []);

  const getOrCreateModuleProgress = useCallback((moduleId: string): ModuleProgress => {
    if (!courseProgress) {
      throw new Error('Course progress not initialized');
    }

    let moduleProgress = courseProgress.modulesProgress.find(mp => mp.moduleId === moduleId);
    
    if (!moduleProgress) {
      moduleProgress = {
        moduleId,
        progress: 0,
        timeSpent: 0,
        isCompleted: false,
        lastAccessedAt: new Date(),
        bookmarks: [],
        quizScores: [],
        assignmentSubmissions: []
      };
      
      setCourseProgress(prev => prev ? {
        ...prev,
        modulesProgress: [...prev.modulesProgress, moduleProgress!]
      } : null);
    }
    
    return moduleProgress;
  }, [courseProgress]);

  const updateModuleProgress = useCallback((moduleId: string, progress: number) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => 
        mp.moduleId === moduleId 
          ? { ...mp, progress: Math.min(100, Math.max(0, progress)), lastAccessedAt: new Date() }
          : mp
      );
      
      // If module doesn't exist, create it
      if (!updatedModules.find(mp => mp.moduleId === moduleId)) {
        updatedModules.push({
          moduleId,
          progress: Math.min(100, Math.max(0, progress)),
          timeSpent: 0,
          isCompleted: progress >= 100,
          lastAccessedAt: new Date(),
          bookmarks: [],
          quizScores: [],
          assignmentSubmissions: []
        });
      }
      
      // Calculate overall progress
      const totalProgress = updatedModules.reduce((sum, mp) => sum + mp.progress, 0);
      const overallProgress = updatedModules.length > 0 ? totalProgress / updatedModules.length : 0;
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        overallProgress,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const completeModule = useCallback((moduleId: string) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => 
        mp.moduleId === moduleId 
          ? { 
              ...mp, 
              progress: 100, 
              isCompleted: true, 
              completedAt: new Date(),
              lastAccessedAt: new Date()
            }
          : mp
      );
      
      // Calculate overall progress
      const completedCount = updatedModules.filter(mp => mp.isCompleted).length;
      const overallProgress = updatedModules.length > 0 ? (completedCount / updatedModules.length) * 100 : 0;
      
      // Check if course is completed
      const isCompleted = completedCount === updatedModules.length && updatedModules.length > 0;
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        overallProgress,
        completedAt: isCompleted ? new Date() : prev.completedAt,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const addTimeSpent = useCallback((moduleId: string, seconds: number) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => 
        mp.moduleId === moduleId 
          ? { ...mp, timeSpent: mp.timeSpent + seconds, lastAccessedAt: new Date() }
          : mp
      );
      
      // If module doesn't exist, create it
      if (!updatedModules.find(mp => mp.moduleId === moduleId)) {
        updatedModules.push({
          moduleId,
          progress: 0,
          timeSpent: seconds,
          isCompleted: false,
          lastAccessedAt: new Date(),
          bookmarks: [],
          quizScores: [],
          assignmentSubmissions: []
        });
      }
      
      const totalTimeSpent = updatedModules.reduce((sum, mp) => sum + mp.timeSpent, 0);
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        totalTimeSpent,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const addBookmark = useCallback((moduleId: string, title: string, timestamp: number, notes?: string) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => {
        if (mp.moduleId === moduleId) {
          const newBookmark = {
            id: `bookmark_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            title,
            timestamp,
            notes,
            createdAt: new Date()
          };
          
          return {
            ...mp,
            bookmarks: [...mp.bookmarks, newBookmark],
            lastAccessedAt: new Date()
          };
        }
        return mp;
      });
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const removeBookmark = useCallback((moduleId: string, bookmarkId: string) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => {
        if (mp.moduleId === moduleId) {
          return {
            ...mp,
            bookmarks: mp.bookmarks.filter(b => b.id !== bookmarkId),
            lastAccessedAt: new Date()
          };
        }
        return mp;
      });
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const updateBookmark = useCallback((moduleId: string, bookmarkId: string, title: string, notes?: string) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => {
        if (mp.moduleId === moduleId) {
          return {
            ...mp,
            bookmarks: mp.bookmarks.map(b => 
              b.id === bookmarkId ? { ...b, title, notes } : b
            ),
            lastAccessedAt: new Date()
          };
        }
        return mp;
      });
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const recordQuizScore = useCallback((moduleId: string, quizId: string, score: number, maxScore: number) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => {
        if (mp.moduleId === moduleId) {
          const existingQuiz = mp.quizScores.find(q => q.quizId === quizId);
          const newQuizScore = {
            quizId,
            score,
            maxScore,
            attempts: existingQuiz ? existingQuiz.attempts + 1 : 1,
            completedAt: new Date()
          };
          
          const updatedQuizScores = existingQuiz
            ? mp.quizScores.map(q => q.quizId === quizId ? newQuizScore : q)
            : [...mp.quizScores, newQuizScore];
          
          return {
            ...mp,
            quizScores: updatedQuizScores,
            lastAccessedAt: new Date()
          };
        }
        return mp;
      });
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const submitAssignment = useCallback((moduleId: string, assignmentId: string) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => {
        if (mp.moduleId === moduleId) {
          const newSubmission = {
            assignmentId,
            submittedAt: new Date(),
            status: 'submitted' as const
          };
          
          return {
            ...mp,
            assignmentSubmissions: [...mp.assignmentSubmissions, newSubmission],
            lastAccessedAt: new Date()
          };
        }
        return mp;
      });
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const gradeAssignment = useCallback((moduleId: string, assignmentId: string, score: number, feedback?: string) => {
    setCourseProgress(prev => {
      if (!prev) return null;
      
      const updatedModules = prev.modulesProgress.map(mp => {
        if (mp.moduleId === moduleId) {
          return {
            ...mp,
            assignmentSubmissions: mp.assignmentSubmissions.map(a => 
              a.assignmentId === assignmentId 
                ? { ...a, score, feedback, status: 'graded' as const }
                : a
            ),
            lastAccessedAt: new Date()
          };
        }
        return mp;
      });
      
      return {
        ...prev,
        modulesProgress: updatedModules,
        lastAccessedAt: new Date()
      };
    });
  }, []);

  const getProgressStats = useCallback((): ProgressStats => {
    try {
      const saved = localStorage.getItem(STATS_STORAGE_KEY);
      return saved ? JSON.parse(saved) : {
        totalCourses: 0,
        completedCourses: 0,
        inProgressCourses: 0,
        totalTimeSpent: 0,
        averageProgress: 0,
        streakDays: 0
      };
    } catch (error) {
      console.error('Error getting progress stats:', error);
      return {
        totalCourses: 0,
        completedCourses: 0,
        inProgressCourses: 0,
        totalTimeSpent: 0,
        averageProgress: 0,
        streakDays: 0
      };
    }
  }, []);

  const getCourseCompletion = useCallback((): number => {
    return courseProgress?.overallProgress || 0;
  }, [courseProgress]);

  const getModuleProgress = useCallback((moduleId: string): ModuleProgress | null => {
    return courseProgress?.modulesProgress.find(mp => mp.moduleId === moduleId) || null;
  }, [courseProgress]);

  const clearProgress = useCallback((courseId: string) => {
    try {
      localStorage.removeItem(`${STORAGE_KEY_PREFIX}${courseId}`);
      setCourseProgress(null);
    } catch (error) {
      console.error('Error clearing progress:', error);
    }
  }, []);

  const isModuleCompleted = useCallback((moduleId: string): boolean => {
    const moduleProgress = courseProgress?.modulesProgress.find(mp => mp.moduleId === moduleId);
    return moduleProgress?.isCompleted || false;
  }, [courseProgress]);

  const getNextIncompleteModule = useCallback((): string | null => {
    const incompleteModule = courseProgress?.modulesProgress.find(mp => !mp.isCompleted);
    return incompleteModule?.moduleId || null;
  }, [courseProgress]);

  const calculateEstimatedCompletion = useCallback((): Date | null => {
    if (!courseProgress || courseProgress.modulesProgress.length === 0) return null;
    
    const completedModules = courseProgress.modulesProgress.filter(mp => mp.isCompleted).length;
    const totalModules = courseProgress.modulesProgress.length;
    const remainingModules = totalModules - completedModules;
    
    if (remainingModules === 0) return null;
    
    // Calculate average time per completed module
    const totalTimeSpent = courseProgress.modulesProgress
      .filter(mp => mp.isCompleted)
      .reduce((sum, mp) => sum + mp.timeSpent, 0);
    
    if (completedModules === 0) return null;
    
    const avgTimePerModule = totalTimeSpent / completedModules;
    const estimatedRemainingTime = remainingModules * avgTimePerModule;
    
    const now = new Date();
    return new Date(now.getTime() + estimatedRemainingTime * 1000);
  }, [courseProgress]);

  return {
    courseProgress,
    updateModuleProgress,
    completeModule,
    addTimeSpent,
    addBookmark,
    removeBookmark,
    updateBookmark,
    recordQuizScore,
    submitAssignment,
    gradeAssignment,
    getProgressStats,
    getCourseCompletion,
    getModuleProgress,
    saveProgress,
    loadProgress,
    clearProgress,
    isModuleCompleted,
    getNextIncompleteModule,
    calculateEstimatedCompletion
  };
}