// Package service 业务逻辑层
package service

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"server/common"
	"server/config"
	"server/modules/user/vo"
	"server/modules/yx/dto"
	"server/modules/yx/entity"
	"server/modules/yx/mapper"
	"server/modules/yx/service"
	"strings"
	"time"

	"gorm.io/gorm"
)

type UserScoreService struct {
	yxUserScoreService        *service.YxUserScoreService
	yxCalculationMajorService *service.YxCalculationMajorService
	mapper                    *mapper.YxUserScoreMapper
}

func (s *UserScoreService) GetUserScoreByUserId(id string) {
	panic("unimplemented")
}

// GetActiveByID 获取当前激活的成绩
func (s *UserScoreService) GetActiveByID(userID string) (vo.UserScoreVO, error) {
	var score entity.YxUserScore
	// 先从Redis获取是否存在
	scoreRedisData, err := config.RDB.Get(context.Background(), common.RedisUserScorePrefix+userID).Result()
	if err != nil {
		// 明确指定字段，提高可读性
		err := config.DB.Model(&entity.YxUserScore{}).
			Where("create_by = ? AND state = ?", userID, "1").
			First(&score).Error
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return vo.UserScoreVO{}, fmt.Errorf("未找到激活的成绩记录")
			}
			return vo.UserScoreVO{}, fmt.Errorf("查询成绩记录失败: %w", err)
		}
		// 缓存到 Redis
		scoreRedisSetData, err := json.Marshal(score)
		if err != nil {
			return vo.UserScoreVO{}, fmt.Errorf("序列化成绩记录失败: %w", err)
		}
		err = config.RDB.Set(context.Background(), common.RedisUserScorePrefix+userID, scoreRedisSetData, common.RedisUserScoreExpire).Err()
		if err != nil {
			return vo.UserScoreVO{}, fmt.Errorf("缓存成绩记录失败: %w", err)
		}
	} else {
		if err := json.Unmarshal([]byte(scoreRedisData), &score); err != nil {
			return vo.UserScoreVO{}, fmt.Errorf("解析 Redis 数据失败: %w", err)
		}
		// 刷新过期时间
		config.RDB.Expire(context.Background(), common.RedisUserScorePrefix+userID, common.RedisUserScoreExpire)
	}

	return s.convertEntityToVo(score), nil
}

// GetByID 根据 ID 获取成绩
func (s *UserScoreService) GetByID(id string) (vo.UserScoreVO, error) {
	var score entity.YxUserScore
	err := config.DB.Model(&entity.YxUserScore{}).
		Where("id = ?", id).
		First(&score).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return vo.UserScoreVO{}, fmt.Errorf("记录不存在")
		}
		return vo.UserScoreVO{}, fmt.Errorf("查询失败: %w", err)
	}

	return s.convertEntityToVo(score), nil
}

// ListByUser 获取用户的成绩分页列表
func (s *UserScoreService) ListByUser(userID string, page, size int) ([]vo.UserScoreVO, int64, error) {
	var scores []entity.YxUserScore
	var total int64

	query := config.DB.Model(&entity.YxUserScore{}).Where("create_by = ?", userID)

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("查询总数失败: %w", err)
	}

	if err := query.Offset((page - 1) * size).Limit(size).Order("create_time desc").Find(&scores).Error; err != nil {
		return nil, 0, fmt.Errorf("查询成绩列表失败: %w", err)
	}

	vos := make([]vo.UserScoreVO, 0, len(scores))
	for i := range scores {
		vos = append(vos, s.convertEntityToVo(scores[i]))
	}

	return vos, total, nil
}

func NewUserScoreService() *UserScoreService {
	return &UserScoreService{
		yxUserScoreService:        service.NewYxUserScoreService(),
		yxCalculationMajorService: service.NewYxCalculationMajorService(),
		mapper:                    mapper.NewYxUserScoreMapper(),
	}
}

// SaveUserScore 保存用户成绩并返回 VO
func (s *UserScoreService) SaveUserScore(req *dto.SaveScoreRequest) (vo.UserScoreVO, error) {
	// 1. 业务验证
	if err := req.Validate(); err != nil {
		return vo.UserScoreVO{}, err
	}

	// 2. DTO 转 Entity
	entityItem := s.convertDtoToEntity(req)
	entityItem.CalculationTableName = "yx_calculation_major_2025_2"
	entityItem.ID = common.GenerateStringID() // 使用新封装的 ID 生成工具
	entityItem.CreateTime = time.Now()
	entityItem.UpdateTime = time.Now()

	// 3. 执行保存操作（可以包含事务）
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("【PANIC】事务执行过程中发生panic: %v", r)
			// 记录详细的栈信息
			fmt.Printf("【PANIC】尝试回滚事务")
			tx.Rollback()
			fmt.Printf("【PANIC】事务已回滚")
		}
	}()

	// 标记该用户的所有旧成绩为历史状态
	if err := tx.Model(&entity.YxUserScore{}).
		Where("create_by = ? AND state = ?", req.CreateBy, "1").
		Updates(map[string]interface{}{"state": "2"}).Error; err != nil {
		tx.Rollback()
		return vo.UserScoreVO{}, fmt.Errorf("更新旧记录失败: %w", err)
	}

	// 保存新的成绩记录
	if err := tx.Create(entityItem).Error; err != nil {
		fmt.Errorf("保存记录失败: %w", err)
		tx.Rollback()
		return vo.UserScoreVO{}, fmt.Errorf("保存记录失败: %w", err)
	}
	userScoreVO := s.convertEntityToVo(*entityItem)

	// 提交事务 - ✅ 快速释放数据库连接
	// if err := tx.Commit().Error; err != nil {
	// 	return vo.UserScoreVO{}, fmt.Errorf("提交事务失败: %w", err)
	// }

	// 根据成绩计算用户的专业信息
	schoolMajorItems, err := s.yxCalculationMajorService.ListByUserQueryType(userScoreVO.ProfessionalCategory,
		userScoreVO.CognitioPolyclinic, userScoreVO.ProfessionalCategoryChildren)
	if err != nil {
		tx.Rollback()
		return vo.UserScoreVO{}, fmt.Errorf("查询专业信息失败: %w", err)
	}

	// 检查录取概率
	s.yxCalculationMajorService.CheckEnrollProbability(&schoolMajorItems, userScoreVO)

	// 插入到数据库
	err = s.yxCalculationMajorService.BatchCreateBySchoolMajorDTO(entityItem.CalculationTableName, schoolMajorItems, userScoreVO.ID)
	if err != nil {
		tx.Rollback()
		return vo.UserScoreVO{}, fmt.Errorf("保存专业信息失败: %w", err)
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return vo.UserScoreVO{}, fmt.Errorf("提交事务失败: %w", err)
	}

	// 清除之前的Redis成绩缓存
	config.RDB.Del(context.Background(), common.RedisUserScorePrefix+req.CreateBy)

	// 更新Redis 数据
	scoreRedisSetData, err := json.Marshal(entityItem)
	err = config.RDB.Set(context.Background(), common.RedisUserScorePrefix+req.CreateBy, scoreRedisSetData, common.RedisUserScoreExpire).Err()
	if err != nil {
		return vo.UserScoreVO{}, fmt.Errorf("缓存成绩记录失败: %w", err)
	}

	return userScoreVO, nil
}

// 私有方法：DTO 转 Entity
func (s *UserScoreService) convertDtoToEntity(req *dto.SaveScoreRequest) *entity.YxUserScore {
	entityItem := entity.YxUserScore{
		CognitioPolyclinic:           req.CognitioPolyclinic,
		Subjects:                     strings.Join(req.SubjectList, ","),
		ProfessionalCategory:         req.ProfessionalCategory,
		ProfessionalCategoryChildren: strings.Join(req.ProfessionalCategoryChildren, ","),
		ProfessionalScore:            *req.ProfessionalScore,
		CulturalScore:                *req.CulturalScore,
		EnglishScore:                 *req.EnglishScore,
		ChineseScore:                 *req.ChineseScore,
		Province:                     req.Province,
		State:                        "1", // 默认状态
		CreateBy:                     req.CreateBy,
	}

	// 映射子专业成绩到具体字段
	if v, ok := req.ProfessionalCategoryChildrenScore["音乐表演声乐"]; ok {
		entityItem.Yybysy = v
	}
	if v, ok := req.ProfessionalCategoryChildrenScore["音乐表演器乐"]; ok {
		entityItem.Yybyqy = v
	}
	if v, ok := req.ProfessionalCategoryChildrenScore["音乐教育"]; ok {
		entityItem.Yyjy = v
	}
	if v, ok := req.ProfessionalCategoryChildrenScore["戏剧影视导演"]; ok {
		entityItem.Xjysdy = v
	}
	if v, ok := req.ProfessionalCategoryChildrenScore["戏剧影视表演"]; ok {
		entityItem.Xjysby = v
	}
	if v, ok := req.ProfessionalCategoryChildrenScore["服装表演"]; ok {
		entityItem.Fzby = v
	}

	return &entityItem
}

// 私有方法：Entity 转 VO
func (s *UserScoreService) convertEntityToVo(item entity.YxUserScore) vo.UserScoreVO {
	voItem := vo.UserScoreVO{
		ID:                                item.ID,
		Type:                              item.Type,
		EducationalLevel:                  item.EducationalLevel,
		CognitioPolyclinic:                item.CognitioPolyclinic,
		ProfessionalCategory:              item.ProfessionalCategory,
		ProfessionalCategoryChildren:      []string{},
		ProfessionalCategoryChildrenScore: make(map[string]float64),
		ProfessionalScore:                 item.ProfessionalScore,
		CulturalScore:                     item.CulturalScore,
		EnglishScore:                      item.EnglishScore,
		ChineseScore:                      item.ChineseScore,
		Province:                          item.Province,
		State:                             item.State,
		CalculationTableName:              item.CalculationTableName,
	}
	if item.Subjects == "" {
		voItem.SubjectList = []string{}
	} else {
		voItem.SubjectList = strings.Split(item.Subjects, ",")
	}

	if item.ProfessionalCategoryChildren == "" {
		voItem.ProfessionalCategoryChildren = []string{}
	} else {
		voItem.ProfessionalCategoryChildren = strings.Split(item.ProfessionalCategoryChildren, ",")
	}

	// 映射具体字段到子专业成绩 Map
	if item.Yybysy > 0 {
		voItem.ProfessionalCategoryChildrenScore["音乐表演声乐"] = item.Yybysy
	}
	if item.Yybyqy > 0 {
		voItem.ProfessionalCategoryChildrenScore["音乐表演器乐"] = item.Yybyqy
	}
	if item.Yyjy > 0 {
		voItem.ProfessionalCategoryChildrenScore["音乐教育"] = item.Yyjy
	}
	if item.Xjysdy > 0 {
		voItem.ProfessionalCategoryChildrenScore["戏剧影视导演"] = item.Xjysdy
	}
	if item.Xjysby > 0 {
		voItem.ProfessionalCategoryChildrenScore["戏剧影视表演"] = item.Xjysby
	}
	if item.Fzby > 0 {
		voItem.ProfessionalCategoryChildrenScore["服装表演"] = item.Fzby
	}

	return voItem
}
