package services

import (
	"time"

	"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/models"
	"gorm.io/gorm"
)

// LearningSessionService 学习会话服务
type LearningSessionService struct {
	db *gorm.DB
}

func NewLearningSessionService(db *gorm.DB) *LearningSessionService {
	return &LearningSessionService{db: db}
}

// StartLearningSession 开始学习会话
func (s *LearningSessionService) StartLearningSession(userID int64, bookID string, dailyGoal int) (*models.LearningSession, error) {
	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	
	// 检查今天是否已有学习会话
	var existingSession models.LearningSession
	err := s.db.Where("user_id = ? AND book_id = ? AND DATE(created_at) = ?", 
		userID, bookID, today.Format("2006-01-02")).First(&existingSession).Error
	
	if err == nil {
		// 已存在会话，返回现有会话
		return &existingSession, nil
	}
	
	if err != gorm.ErrRecordNotFound {
		return nil, err
	}
	
	// 创建新的学习会话
	session := &models.LearningSession{
		UserID:        userID,
		BookID:        bookID,
		DailyGoal:     dailyGoal,
		NewWordsCount: 0,
		ReviewCount:   0,
		MasteredCount: 0,
		StartedAt:     now,
	}
	
	if err := s.db.Create(session).Error; err != nil {
		return nil, err
	}
	
	return session, nil
}

// GetTodayLearningTasks 获取今日学习任务（新词+复习词）
// 学习逻辑：每天学习的单词 = 用户选择的新词数 + 当日所有需要复习的单词
func (s *LearningSessionService) GetTodayLearningTasks(userID int64, bookID string, newWordsLimit int) (map[string]interface{}, error) {
	now := time.Now()
	
	// 1. 获取所有需要复习的单词（到期的，不限数量）
	var reviewWords []models.UserWordProgress
	err := s.db.Raw(`
		SELECT uwp.* 
		FROM ai_user_word_progress uwp
		INNER JOIN ai_vocabulary_book_words vbw ON CAST(vbw.vocabulary_id AS UNSIGNED) = uwp.vocabulary_id
		WHERE uwp.user_id = ? 
		AND vbw.book_id = ?
		AND uwp.status IN ('learning', 'reviewing')
		AND (uwp.next_review_at IS NULL OR uwp.next_review_at <= ?)
		ORDER BY uwp.next_review_at ASC
	`, userID, bookID, now).Scan(&reviewWords).Error
	
	if err != nil {
		return nil, err
	}
	
	// 2. 获取新单词（从未学习的）
	var newWords []int64
	err = s.db.Raw(`
		SELECT CAST(vbw.vocabulary_id AS UNSIGNED) as id
		FROM ai_vocabulary_book_words vbw
		LEFT JOIN ai_user_word_progress uwp ON uwp.vocabulary_id = CAST(vbw.vocabulary_id AS UNSIGNED) AND uwp.user_id = ?
		WHERE vbw.book_id = ?
		AND uwp.id IS NULL
		ORDER BY vbw.sort_order ASC
		LIMIT ?
	`, userID, bookID, newWordsLimit).Scan(&newWords).Error
	
	if err != nil {
		return nil, err
	}
	
	// 3. 获取已掌握的单词统计
	var masteredCount int64
	s.db.Model(&models.UserWordProgress{}).
		Joins("INNER JOIN ai_vocabulary_book_words vbw ON CAST(vbw.vocabulary_id AS UNSIGNED) = ai_user_word_progress.vocabulary_id").
		Where("ai_user_word_progress.user_id = ? AND vbw.book_id = ? AND ai_user_word_progress.status = 'mastered'", 
			userID, bookID).
		Count(&masteredCount)
	
	// 4. 获取词汇书总词数
	var totalWords int64
	s.db.Model(&models.VocabularyBookWord{}).Where("book_id = ?", bookID).Count(&totalWords)
	
	return map[string]interface{}{
		"newWords":      newWords,
		"reviewWords":   reviewWords,
		"masteredCount": masteredCount,
		"totalWords":    totalWords,
		"progress":      float64(masteredCount) / float64(totalWords) * 100,
	}, nil
}

// RecordWordStudy 记录单词学习结果
func (s *LearningSessionService) RecordWordStudy(userID int64, wordID int64, difficulty string) (*models.UserWordProgress, error) {
	now := time.Now()
	
	var progress models.UserWordProgress
	err := s.db.Where("user_id = ? AND vocabulary_id = ?", userID, wordID).First(&progress).Error
	
	isNew := false
	if err == gorm.ErrRecordNotFound {
		isNew = true
		// 创建新记录
		progress = models.UserWordProgress{
			UserID:         userID,
			VocabularyID:   wordID,
			Status:         "learning",
			StudyCount:     0,
			CorrectCount:   0,
			WrongCount:     0,
			Proficiency:    0,
			ReviewInterval: 1,
			FirstStudiedAt: now,
			LastStudiedAt:  now,
		}
	} else if err != nil {
		return nil, err
	}
	
	// 更新学习统计
	progress.StudyCount++
	progress.LastStudiedAt = now
	
	// 根据难度更新进度和计算下次复习时间
	nextInterval := s.calculateNextInterval(progress.ReviewInterval, difficulty, progress.StudyCount)
	
	switch difficulty {
	case "forgot":
		// 完全忘记：重置
		progress.WrongCount++
		progress.Proficiency = max(0, progress.Proficiency-30)
		progress.ReviewInterval = 1
		progress.Status = "learning"
		progress.NextReviewAt = &[]time.Time{now.Add(24 * time.Hour)}[0]
		
	case "hard":
		// 困难：小幅增加间隔
		progress.WrongCount++
		progress.Proficiency = max(0, progress.Proficiency-10)
		progress.ReviewInterval = max(1, nextInterval/2)
		nextReview := now.Add(time.Duration(progress.ReviewInterval) * 24 * time.Hour)
		progress.NextReviewAt = &nextReview
		
	case "good":
		// 一般：正常增加
		progress.CorrectCount++
		progress.Proficiency = min(100, progress.Proficiency+15)
		progress.ReviewInterval = nextInterval
		nextReview := now.Add(time.Duration(progress.ReviewInterval) * 24 * time.Hour)
		progress.NextReviewAt = &nextReview
		
		// 更新状态
		if progress.StudyCount >= 3 && progress.Proficiency >= 60 {
			progress.Status = "reviewing"
		}
		
	case "easy":
		// 容易：大幅增加间隔
		progress.CorrectCount++
		progress.Proficiency = min(100, progress.Proficiency+25)
		progress.ReviewInterval = int(float64(nextInterval) * 1.5)
		nextReview := now.Add(time.Duration(progress.ReviewInterval) * 24 * time.Hour)
		progress.NextReviewAt = &nextReview
		
		// 更新状态
		if progress.StudyCount >= 2 && progress.Proficiency >= 70 {
			progress.Status = "reviewing"
		}
		
	case "perfect":
		// 完美：最大间隔
		progress.CorrectCount++
		progress.Proficiency = 100
		progress.ReviewInterval = nextInterval * 2
		nextReview := now.Add(time.Duration(progress.ReviewInterval) * 24 * time.Hour)
		progress.NextReviewAt = &nextReview
		
		// 达到掌握标准
		if progress.StudyCount >= 5 && progress.Proficiency >= 90 {
			progress.Status = "mastered"
			progress.MasteredAt = &now
		} else {
			progress.Status = "reviewing"
		}
	}
	
	// 保存或更新
	if isNew {
		if err := s.db.Create(&progress).Error; err != nil {
			return nil, err
		}
	} else {
		if err := s.db.Save(&progress).Error; err != nil {
			return nil, err
		}
	}
	
	// 更新今日学习会话的计数器
	s.updateTodaySessionStats(userID)
	
	return &progress, nil
}

// updateTodaySessionStats 更新今日学习会话的统计数据
func (s *LearningSessionService) updateTodaySessionStats(userID int64) {
	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	
	// 查找今日会话
	var session models.LearningSession
	err := s.db.Where("user_id = ? AND DATE(created_at) = ?", userID, today.Format("2006-01-02")).First(&session).Error
	if err != nil {
		return // 没有会话就不更新
	}
	
	// 统计今日学习的单词
	var stats struct {
		NewWords      int64
		ReviewWords   int64
		MasteredWords int64
	}
	
	// 今日新学单词（首次学习时间是今天）
	s.db.Model(&models.UserWordProgress{}).
		Where("user_id = ? AND DATE(first_studied_at) = ?", userID, today.Format("2006-01-02")).
		Count(&stats.NewWords)
	
	// 今日复习单词（首次学习不是今天，但最后学习是今天）
	s.db.Model(&models.UserWordProgress{}).
		Where("user_id = ? AND DATE(first_studied_at) != ? AND DATE(last_studied_at) = ?", 
			userID, today.Format("2006-01-02"), today.Format("2006-01-02")).
		Count(&stats.ReviewWords)
	
	// 今日掌握单词（掌握时间是今天）
	s.db.Model(&models.UserWordProgress{}).
		Where("user_id = ? AND DATE(mastered_at) = ?", userID, today.Format("2006-01-02")).
		Count(&stats.MasteredWords)
	
	// 更新会话
	session.NewWordsCount = int(stats.NewWords)
	session.ReviewCount = int(stats.ReviewWords)
	session.MasteredCount = int(stats.MasteredWords)
	
	s.db.Save(&session)
	
	// 同时更新词汇书级别的进度
	s.updateBookProgress(userID, session.BookID)
}

// updateBookProgress 更新词汇书级别的学习进度
func (s *LearningSessionService) updateBookProgress(userID int64, bookID string) {
	// 统计该词汇书的总体进度
	var progress struct {
		TotalLearned  int64
		TotalMastered int64
	}
	
	// 统计已学习的单词数（该词汇书中的所有已学习单词）
	s.db.Raw(`
		SELECT COUNT(DISTINCT uwp.vocabulary_id) as total_learned,
		       SUM(CASE WHEN uwp.status = 'mastered' THEN 1 ELSE 0 END) as total_mastered
		FROM ai_user_word_progress uwp
		INNER JOIN ai_vocabulary_book_words vbw ON CAST(vbw.vocabulary_id AS UNSIGNED) = uwp.vocabulary_id
		WHERE uwp.user_id = ? AND vbw.book_id = ?
	`, userID, bookID).Scan(&progress)
	
	// 获取词汇书总单词数
	var totalWords int64
	s.db.Model(&models.VocabularyBookWord{}).Where("book_id = ?", bookID).Count(&totalWords)
	
	// 计算进度百分比
	progressPercentage := 0.0
	if totalWords > 0 {
		progressPercentage = float64(progress.TotalLearned) / float64(totalWords) * 100
	}
	
	// 更新或创建词汇书进度记录
	now := time.Now()
	var bookProgress models.UserVocabularyBookProgress
	err := s.db.Where("user_id = ? AND book_id = ?", userID, bookID).First(&bookProgress).Error
	
	if err == gorm.ErrRecordNotFound {
		// 创建新记录
		bookProgress = models.UserVocabularyBookProgress{
			UserID:             userID,
			BookID:             bookID,
			LearnedWords:       int(progress.TotalLearned),
			MasteredWords:      int(progress.TotalMastered),
			ProgressPercentage: progressPercentage,
			StartedAt:          now,
			LastStudiedAt:      now,
		}
		s.db.Create(&bookProgress)
	} else if err == nil {
		// 更新现有记录
		bookProgress.LearnedWords = int(progress.TotalLearned)
		bookProgress.MasteredWords = int(progress.TotalMastered)
		bookProgress.ProgressPercentage = progressPercentage
		bookProgress.LastStudiedAt = now
		s.db.Save(&bookProgress)
	}
}

// calculateNextInterval 计算下次复习间隔（天数）
func (s *LearningSessionService) calculateNextInterval(currentInterval int, difficulty string, studyCount int) int {
	// 基于SuperMemo SM-2算法的简化版本
	baseIntervals := []int{1, 3, 7, 14, 30, 60, 120, 240}
	
	if studyCount <= len(baseIntervals) {
		return baseIntervals[min(studyCount-1, len(baseIntervals)-1)]
	}
	
	// 超过基础序列后，根据难度调整
	switch difficulty {
	case "forgot":
		return 1
	case "hard":
		return max(1, int(float64(currentInterval)*0.8))
	case "good":
		return int(float64(currentInterval) * 1.5)
	case "easy":
		return int(float64(currentInterval) * 2.5)
	case "perfect":
		return currentInterval * 3
	default:
		return currentInterval
	}
}

// UpdateSessionProgress 更新学习会话进度
func (s *LearningSessionService) UpdateSessionProgress(sessionID int64, newWords, reviewWords, masteredWords int) error {
	return s.db.Model(&models.LearningSession{}).
		Where("id = ?", sessionID).
		Updates(map[string]interface{}{
			"new_words_count": newWords,
			"review_count":    reviewWords,
			"mastered_count":  masteredWords,
			"completed_at":    time.Now(),
		}).Error
}

// GetLearningStatistics 获取学习统计
func (s *LearningSessionService) GetLearningStatistics(userID int64, bookID string) (map[string]interface{}, error) {
	// 今日学习统计
	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	
	var todaySession models.LearningSession
	s.db.Where("user_id = ? AND book_id = ? AND DATE(created_at) = ?", 
		userID, bookID, today.Format("2006-01-02")).First(&todaySession)
	
	// 总体统计
	var stats struct {
		TotalLearned  int64
		TotalMastered int64
		AvgProficiency float64
	}
	
	s.db.Model(&models.UserWordProgress{}).
		Select("COUNT(*) as total_learned, SUM(CASE WHEN status = 'mastered' THEN 1 ELSE 0 END) as total_mastered, AVG(proficiency) as avg_proficiency").
		Joins("INNER JOIN ai_vocabulary_book_words vbw ON CAST(vbw.vocabulary_id AS UNSIGNED) = ai_user_word_progress.vocabulary_id").
		Where("ai_user_word_progress.user_id = ? AND vbw.book_id = ?", userID, bookID).
		Scan(&stats)
	
	// 连续学习天数
	var streakDays int
	s.db.Raw(`
		SELECT COUNT(DISTINCT DATE(created_at)) 
		FROM ai_learning_sessions 
		WHERE user_id = ? AND book_id = ?
		AND created_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
	`, userID, bookID).Scan(&streakDays)
	
	return map[string]interface{}{
		"todayNewWords":    todaySession.NewWordsCount,
		"todayReview":      todaySession.ReviewCount,
		"todayMastered":    todaySession.MasteredCount,
		"totalLearned":     stats.TotalLearned,
		"totalMastered":    stats.TotalMastered,
		"avgProficiency":   stats.AvgProficiency,
		"streakDays":       streakDays,
	}, nil
}

// GetTodayReviewWords 获取今日需要复习的所有单词（跨所有词汇书）
func (s *LearningSessionService) GetTodayReviewWords(userID int64) ([]map[string]interface{}, error) {
	now := time.Now()
	
	// 获取所有到期需要复习的单词
	var reviewWords []models.UserWordProgress
	err := s.db.Raw(`
		SELECT uwp.* 
		FROM ai_user_word_progress uwp
		WHERE uwp.user_id = ? 
		AND uwp.status IN ('learning', 'reviewing')
		AND (uwp.next_review_at IS NULL OR uwp.next_review_at <= ?)
		ORDER BY uwp.next_review_at ASC
		LIMIT 100
	`, userID, now).Scan(&reviewWords).Error
	
	if err != nil {
		return nil, err
	}
	
	// 获取单词详情
	result := make([]map[string]interface{}, 0)
	for _, progress := range reviewWords {
		result = append(result, map[string]interface{}{
			"vocabulary_id":    progress.VocabularyID,
			"status":           progress.Status,
			"proficiency":      progress.Proficiency,
			"study_count":      progress.StudyCount,
			"next_review_at":   progress.NextReviewAt,
			"last_studied_at":  progress.LastStudiedAt,
		})
	}
	
	return result, nil
}

// GetTodayOverallStatistics 获取今日总体学习统计（所有词汇书）
func (s *LearningSessionService) GetTodayOverallStatistics(userID int64) (map[string]interface{}, error) {
	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	
	// 今日学习的单词总数
	var todayStats struct {
		NewWords    int64
		ReviewWords int64
		TotalStudied int64
	}
	
	// 统计今日新学习的单词
	s.db.Model(&models.UserWordProgress{}).
		Where("user_id = ? AND DATE(first_studied_at) = ?", userID, today.Format("2006-01-02")).
		Count(&todayStats.NewWords)
	
	// 统计今日复习的单词（今天学习但不是第一次）
	s.db.Model(&models.UserWordProgress{}).
		Where("user_id = ? AND DATE(first_studied_at) != ? AND DATE(last_studied_at) = ?", 
			userID, today.Format("2006-01-02"), today.Format("2006-01-02")).
		Count(&todayStats.ReviewWords)
	
	todayStats.TotalStudied = todayStats.NewWords + todayStats.ReviewWords
	
	// 总体统计
	var totalStats struct {
		TotalLearned  int64
		TotalMastered int64
	}
	
	s.db.Model(&models.UserWordProgress{}).
		Select("COUNT(*) as total_learned, SUM(CASE WHEN status = 'mastered' THEN 1 ELSE 0 END) as total_mastered").
		Where("user_id = ?", userID).
		Scan(&totalStats)
	
	// 连续学习天数（最近30天内有学习记录的天数）
	var streakDays int64
	s.db.Raw(`
		SELECT COUNT(DISTINCT DATE(last_studied_at))
		FROM ai_user_word_progress
		WHERE user_id = ?
		AND last_studied_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
	`, userID).Scan(&streakDays)
	
	return map[string]interface{}{
		"todayNewWords":    todayStats.NewWords,
		"todayReviewWords": todayStats.ReviewWords,
		"todayTotalStudied": todayStats.TotalStudied,
		"totalLearned":     totalStats.TotalLearned,
		"totalMastered":    totalStats.TotalMastered,
		"streakDays":       streakDays,
	}, nil
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
