package org.dromara.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.system.domain.GameEventProject;
import org.dromara.system.domain.GameScore;
import org.dromara.system.domain.GameTeam;
import org.dromara.system.domain.vo.AthleteScoreVo;
import org.dromara.system.mapper.GameEventProjectMapper;
import org.dromara.system.mapper.GameScoreMapper;
import org.dromara.system.mapper.GameTeamMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.system.domain.bo.GameAthleteBo;
import org.dromara.system.domain.vo.GameAthleteVo;
import org.dromara.system.domain.GameAthlete;
import org.dromara.system.mapper.GameAthleteMapper;
import org.dromara.system.service.IGameAthleteService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 参赛队员Service业务层处理
 *
 * @author zlt
 * @date 2025-07-30
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class GameAthleteServiceImpl implements IGameAthleteService {

    private final GameAthleteMapper baseMapper;

    @Autowired
    private GameTeamMapper gameTeamMapper;
    @Autowired
    private GameEventProjectMapper gameEventProjectMapper;
    @Autowired
    private GameScoreMapper gameScoreMapper;

    /**
     * 根据赛事ID查询参赛者积分信息列表
     *
     * @param eventId 赛事ID
     * @return 参赛者积分信息列表
     */
    @Override
    public List<AthleteScoreVo> queryAthleteScoreList(Long eventId) {
        // 查询该赛事下的所有运动员
        GameAthleteBo athleteBo = new GameAthleteBo();
        athleteBo.setEventId(eventId);
        List<GameAthleteVo> athleteList = queryList(athleteBo);

        if (CollUtil.isEmpty(athleteList)) {
            return Collections.emptyList();
        }

        // 获取所有队伍信息
        Set<Long> teamIds = athleteList.stream()
            .map(GameAthleteVo::getTeamId)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());

        Map<Long, String> teamMap = new HashMap<>();
        if (CollUtil.isNotEmpty(teamIds)) {
            LambdaQueryWrapper<GameTeam> teamWrapper = new LambdaQueryWrapper<>();
            teamWrapper.in(GameTeam::getTeamId, teamIds);
            List<GameTeam> teamList = gameTeamMapper.selectList(teamWrapper);
            teamMap = teamList.stream()
                .collect(Collectors.toMap(GameTeam::getTeamId, GameTeam::getTeamName));
        }

        // 获取所有项目信息
        LambdaQueryWrapper<GameEventProject> projectWrapper = new LambdaQueryWrapper<>();
        projectWrapper.eq(GameEventProject::getEventId, eventId);
        List<GameEventProject> projectList = gameEventProjectMapper.selectList(projectWrapper);
        Map<Long, String> projectMap = projectList.stream()
            .collect(Collectors.toMap(GameEventProject::getProjectId, GameEventProject::getProjectName));

        // 获取所有成绩信息
        LambdaQueryWrapper<GameScore> scoreWrapper = new LambdaQueryWrapper<>();
        scoreWrapper.eq(GameScore::getEventId, eventId);
        List<GameScore> scoreList = gameScoreMapper.selectList(scoreWrapper);
        Map<Long, List<GameScore>> athleteScoreMap = scoreList.stream()
            .filter(score -> score.getAthleteId() != null)
            .collect(Collectors.groupingBy(GameScore::getAthleteId));

        // 构建返回结果
        Map<Long, String> finalTeamMap = teamMap;
        return athleteList.stream().map(athlete -> {
            AthleteScoreVo vo = new AthleteScoreVo();
            vo.setAthleteName(athlete.getName());
            vo.setTeamName(finalTeamMap.getOrDefault(athlete.getTeamId(), "未分配队伍"));

            List<GameScore> scores = athleteScoreMap.getOrDefault(athlete.getAthleteId(), Collections.emptyList());
            List<AthleteScoreVo.ScoreDetail> scoreDetails = scores.stream().map(score -> {
                AthleteScoreVo.ScoreDetail detail = new AthleteScoreVo.ScoreDetail();
                detail.setProjectName(projectMap.getOrDefault(score.getProjectId(), "未知项目"));
                detail.setScorePoint(score.getScorePoint());
                detail.setRank(score.getScoreRank());
                return detail;
            }).collect(Collectors.toList());

            vo.setScoreDetails(scoreDetails);
            Long totalScore = scoreDetails.stream()
                .map(AthleteScoreVo.ScoreDetail::getScorePoint)
                .filter(Objects::nonNull)
                .reduce(0L, Long::sum);
            vo.setTotalScore(totalScore);

            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 查询参赛队员
     *
     * @param athleteId 主键
     * @return 参赛队员
     */
    @Override
    public GameAthleteVo queryById(Long athleteId){
        return baseMapper.selectVoById(athleteId);
    }

    /**
     * 分页查询参赛队员列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 参赛队员分页列表
     */
    @Override
    public TableDataInfo<GameAthleteVo> queryPageList(GameAthleteBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<GameAthlete> lqw = buildQueryWrapper(bo);
        Page<GameAthleteVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的参赛队员列表
     *
     * @param bo 查询条件
     * @return 参赛队员列表
     */
    @Override
    public List<GameAthleteVo> queryList(GameAthleteBo bo) {
        LambdaQueryWrapper<GameAthlete> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<GameAthlete> buildQueryWrapper(GameAthleteBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<GameAthlete> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(GameAthlete::getAthleteId);
        lqw.eq(bo.getEventId() != null, GameAthlete::getEventId, bo.getEventId());
        lqw.eq(bo.getTeamId() != null, GameAthlete::getTeamId, bo.getTeamId());
        lqw.eq(StringUtils.isNotBlank(bo.getAthleteCode()), GameAthlete::getAthleteCode, bo.getAthleteCode());
        lqw.like(StringUtils.isNotBlank(bo.getName()), GameAthlete::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getGroupType()), GameAthlete::getGroupType, bo.getGroupType());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), GameAthlete::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增参赛队员
     *
     * @param bo 参赛队员
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(GameAthleteBo bo) {
        GameAthlete add = MapstructUtils.convert(bo, GameAthlete.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setAthleteId(add.getAthleteId());
        }
        return flag;
    }

    /**
     * 修改参赛队员
     *
     * @param bo 参赛队员
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(GameAthleteBo bo) {
        GameAthlete update = MapstructUtils.convert(bo, GameAthlete.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(GameAthlete entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除参赛队员信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
