package com.micer.easyball.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.micer.easyball.controller.FileController;
import com.micer.easyball.mapper.*;
import com.micer.easyball.pojo.*;
import com.micer.easyball.pojo.Dto.*;
import com.micer.easyball.service.GameService;
import com.micer.easyball.utils.JwtUtil;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

import static java.lang.Math.min;

@Service
public class GameServiceImpl implements GameService {

    @Autowired
    PlayerLastClubMapper playerLastClubMapper;

    @Autowired
    GameMapper gameMapper;

    @Autowired
    ClubMapper clubMapper;

    @Autowired
    GamePlayerMapper gamePlayerMapper;

    @Autowired
    GameImageMapper gameImageMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    EventMapper eventMapper;

    @Autowired
    FileController fileController;

    @Autowired
    ClubPlayerMapper clubPlayerMapper;

    @Override
    public ResponseResult getGames(Long year, Boolean option)
    {
        // 获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId();

        // 获取当前俱乐部ID
        PlayerLastClub playerLastClub = playerLastClubMapper.selectOne(new QueryWrapper<PlayerLastClub>().eq("player_id", userId));
        String clubId = playerLastClub.getLastClubId();

        // 获取当前俱乐部
        Club club = clubMapper.selectById(clubId);

        // 获取当前俱乐部当前年份的所有比赛
        List<Game> gameList = gameMapper.selectList(new QueryWrapper<Game>().eq("year", year).eq("our_team_id", clubId));

        List<GameDto> gameDtoList = new ArrayList<>();
        for (Game game: gameList)
        {
            GameDto gameDto = new GameDto(game);

            // 获取俱乐部名
            gameDto.setOurTeamName(club.getName());

            // 获取赛事ID
            Event event = eventMapper.selectById(game.getEventId());
            gameDto.setEventName(event.getName());

            // 获取比赛球员信息
            List<GamePlayer> gamePlayerList = gamePlayerMapper.selectList(new QueryWrapper<GamePlayer>().eq("game_id", game.getId()));

            List<GamePlayerDto> gamePlayerDtoList = new ArrayList<>();
            for (GamePlayer gamePlayer: gamePlayerList)
            {
                String playerName = userMapper.selectById(gamePlayer.getPlayerId()).getUsername();
                GamePlayerDto gamePlayerDto = new GamePlayerDto(gamePlayer);
                gamePlayerDto.setPlayerName(playerName);
                gamePlayerDtoList.add(gamePlayerDto);
            }

            // 按球员名排序
            HanyuPinyinOutputFormat pinyinOutputFormat = new HanyuPinyinOutputFormat();
            Collections.sort(gamePlayerDtoList, new Comparator<GamePlayerDto>() {
                @Override
                public int compare(GamePlayerDto o1, GamePlayerDto o2) {
                    String py1 = null;
                    String py2 = null;
                    try {
                        py1 = PinyinHelper.toHanYuPinyinString(o1.getPlayerName(), pinyinOutputFormat, " ", true);
                        py2 = PinyinHelper.toHanYuPinyinString(o2.getPlayerName(), pinyinOutputFormat, " ", true);
                    } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
                        badHanyuPinyinOutputFormatCombination.printStackTrace();
                    }
                    return py1.compareTo(py2);
                }
            });

            gameDto.setPlayerList(gamePlayerDtoList);

            // 获取比赛照片
            List<GameImage> gameImageList = gameImageMapper.selectList(new QueryWrapper<GameImage>().eq("game_id", game.getId()));

            // 对照片顺序排序
            Collections.sort(gameImageList, new Comparator<GameImage>() {
                @Override
                public int compare(GameImage o1, GameImage o2) {
                    return o1.getImageRank().compareTo(o2.getImageRank());
                }
            });

            // 获取照片路径
            List<String> imagePathList = new ArrayList<>();
            for (GameImage gameImage: gameImageList)
            {
                imagePathList.add(gameImage.getImagePath());
            }
            gameDto.setImagePathList(imagePathList);

            gameDtoList.add(gameDto);
        }


        // 对场次排序
        if (option)
        {
            Collections.sort(gameDtoList, new Comparator<GameDto>() {
                @Override
                public int compare(GameDto o1, GameDto o2) {
                    return o1.getDate().compareTo(o2.getDate());
                }
            });
        } else
        {
            Collections.sort(gameDtoList, new Comparator<GameDto>() {
                @Override
                public int compare(GameDto o1, GameDto o2) {
                    return o2.getDate().compareTo(o1.getDate());
                }
            });
        }

        return new ResponseResult(200, "成功", gameDtoList);
    }

    @Override
    public ResponseResult getNewGameId() {
        String uuid = JwtUtil.getUUID();
        return new ResponseResult(200, "成功", uuid);
    }

    @Override
    @Transactional
    public ResponseResult addGame(GameDto gameDto) {
        // 校验比赛ID
        if (Objects.isNull(gameDto.getId()))
        {
            return new ResponseResult(450, "需要比赛ID");
        }

        // 校验日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = sdf.format(gameDto.getDate());
        if (!gameDto.getYear().equals(Long.parseLong(dateStr.substring(0, 4))))
        {
            return new ResponseResult(451, "年份错误");
        }

        // 校验球员是否存在（一般用不到）
        for (GamePlayerDto gamePlayerDto: gameDto.getPlayerList())
        {
            User user = userMapper.selectById(gamePlayerDto.getPlayerId());
            if (Objects.isNull(user))
            {
                return new ResponseResult(452, "球员不存在", gamePlayerDto.getPlayerName());
            }
        }

        // 校验赛事是否存在（一般用不到）
        Event event = eventMapper.selectById(gameDto.getEventId());
        if (Objects.isNull(event))
        {
            return new ResponseResult(453, "赛事不存在");
        }

        // 校验进球得分
        int goolSum = 0;
        for (GamePlayerDto gamePlayerDto: gameDto.getPlayerList())
        {
            goolSum += gamePlayerDto.getGoal();
        }
        if (goolSum > gameDto.getOurScore())
        {
            return new ResponseResult(454, "球员进球数总和不能超过总得分");
        }

        // 校验助攻
        int assistSum = 0;
        for (GamePlayerDto gamePlayerDto: gameDto.getPlayerList())
        {
            assistSum += gamePlayerDto.getGoal();
        }
        if (assistSum > gameDto.getOurScore() * 2)
        {
            return new ResponseResult(455, "球员助攻数总和不能超过总得分两倍");
        }

        // 获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId();

        // 获取当前俱乐部ID
        PlayerLastClub playerLastClub = playerLastClubMapper.selectOne(new QueryWrapper<PlayerLastClub>().eq("player_id", userId));
        String clubId = playerLastClub.getLastClubId();

        // 将比赛加入数据库
        gameDto.setOurTeamId(clubId);
        Game game = gameDto;
        gameMapper.insert(game);

        // 将比赛中的球员信息加入数据库
        for (GamePlayerDto gamePlayerDto: gameDto.getPlayerList())
        {
            GamePlayer gamePlayer = gamePlayerDto;
            gamePlayer.setGameDate(game.getDate());
            gamePlayer.setGameId(game.getId());
            gamePlayer.setId(JwtUtil.getUUID());
            gamePlayer.setClubId(clubId);
            gamePlayerMapper.insert(gamePlayer);
        }

        // 将比赛照片信息加入数据库
        Long rank = new Long(1);
        for (String imagePath: gameDto.getImagePathList())
        {
            GameImage gameImage = new GameImage(JwtUtil.getUUID(), game.getId(), imagePath, new Date(System.currentTimeMillis()), rank);
            gameImageMapper.insert(gameImage);
            rank++;
        }

        return new ResponseResult(200, "成功");
    }

    @Override
    @Transactional
    public ResponseResult deleteGame(String gameId) {
        // 获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId();

        // 获取当前俱乐部ID
        PlayerLastClub playerLastClub = playerLastClubMapper.selectOne(new QueryWrapper<PlayerLastClub>().eq("player_id", userId));
        String clubId = playerLastClub.getLastClubId();

        // 获取比赛信息
        Game game = gameMapper.selectById(gameId);

        // 校验俱乐部信息
        if (Objects.isNull(game) || (!clubId.equals(game.getOurTeamId())))
        {
            return new ResponseResult(456, "比赛不存在");
        }

        // 删除比赛信息
        fileController.deleteGameImages(gameId);

        gameImageMapper.delete(new QueryWrapper<GameImage>().eq("game_id", gameId));
        gamePlayerMapper.delete(new QueryWrapper<GamePlayer>().eq("game_id", gameId));
        gameMapper.deleteById(gameId);

        return new ResponseResult(200, "删除成功");
    }

    @Override
    @Transactional
    public ResponseResult editGame(com.micer.easyball.pojo.Dto.GameUpdateDto dto) {
        // 1. 参数校验
        if (Objects.isNull(dto) || Objects.isNull(dto.getId())) {
            return new ResponseResult(450, "需要比赛ID");
        }

        // 2. 校验资源所有权并获取数据库记录
        // 获取当前用户和俱乐部
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId();
        PlayerLastClub playerLastClub = playerLastClubMapper.selectOne(new QueryWrapper<PlayerLastClub>().eq("player_id", userId));
        String clubId = playerLastClub.getLastClubId();

        Game dbGame = gameMapper.selectById(dto.getId());
        if (Objects.isNull(dbGame)) {
            return new ResponseResult(404, "比赛不存在");
        }
        if (!clubId.equals(dbGame.getOurTeamId())) {
            System.out.println("SECURITY: unauthorized editGame attempt by user " + userId + " on game " + dto.getId());
            return new ResponseResult(403, "您没有权限修改其他俱乐部的比赛数据");
        }

        // 3. 严格白名单赋值：仅更新允许客户端修改的字段
        if (dto.getVenue() != null) {
            dbGame.setVenue(dto.getVenue());
        }
        if (dto.getDate() != null) {
            dbGame.setDate(dto.getDate());
        }

        // 4. 保存更新
        gameMapper.updateById(dbGame);

        return new ResponseResult(200, "修改成功");
    }

    @Override
    public ResponseResult getClubStatistics(Long year) {
        // 获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId();

        // 获取当前俱乐部ID
        PlayerLastClub playerLastClub = playerLastClubMapper.selectOne(new QueryWrapper<PlayerLastClub>().eq("player_id", userId));
        String clubId = playerLastClub.getLastClubId();

        // 获取当前俱乐部
        Club club = clubMapper.selectById(clubId);

        // 获取当前俱乐部当前年份的所有比赛
        List<Game> gameList = gameMapper.selectList(new QueryWrapper<Game>().eq("year", year).eq("our_team_id", clubId));

        // 统计
        ClubStatisticsDto clubStatistics = new ClubStatisticsDto();
        for (Game game: gameList)
        {
            clubStatistics.setSession(clubStatistics.getSession() + 1L);
            clubStatistics.setOurGoal(clubStatistics.getOurGoal() + game.getOurScore());
            clubStatistics.setOpponentGoal(clubStatistics.getOpponentGoal() + game.getOpponentScore());
            if (game.getOurScore().compareTo(game.getOpponentScore()) > 0)
            {
                clubStatistics.setWin(clubStatistics.getWin() + 1L);
            } else if (game.getOurScore().compareTo(game.getOpponentScore()) == 0)
            {
                clubStatistics.setTie(clubStatistics.getTie() + 1L);
            } else
            {
                clubStatistics.setLose(clubStatistics.getLose() + 1L);
            }

            // 获取比赛球员信息
            List<GamePlayer> gamePlayerList = gamePlayerMapper.selectList(new QueryWrapper<GamePlayer>().eq("game_id", game.getId()));

            for (GamePlayer gamePlayer: gamePlayerList)
            {
                PlayerDto playerDto = new PlayerDto(gamePlayer);
                int pos = clubStatistics.findPlayer(gamePlayer.getPlayerId());

                // 该球员首次被访问
                if (pos == -1)
                {
                    String playerName = userMapper.selectById(gamePlayer.getPlayerId()).getUsername();
                    playerDto.setPlayerName(playerName);
                    clubStatistics.getPlayerList().add(playerDto);
                } else
                {
                    clubStatistics.getPlayerList().get(pos).setAppearance(clubStatistics.getPlayerList().get(pos).getAppearance() + playerDto.getAppearance());
                    clubStatistics.getPlayerList().get(pos).setMvp(clubStatistics.getPlayerList().get(pos).getMvp() + playerDto.getMvp());
                    clubStatistics.getPlayerList().get(pos).setGoal(clubStatistics.getPlayerList().get(pos).getGoal() + playerDto.getGoal());
                    clubStatistics.getPlayerList().get(pos).setAssist(clubStatistics.getPlayerList().get(pos).getAssist() + playerDto.getAssist());
                }
            }
        }

        // 收集Top射手
        Collections.sort(clubStatistics.getPlayerList(), new Comparator<PlayerDto>() {
            @Override
            public int compare(PlayerDto o1, PlayerDto o2) {
                return o2.getGoal().compareTo(o1.getGoal());
            }
        });
        for (int i = 0; i < min(3, clubStatistics.getPlayerList().size()); i++)
        {
            if (clubStatistics.getPlayerList().get(i).getGoal().compareTo(0L) > 0)
            {
                clubStatistics.getTopShooter().add(clubStatistics.getPlayerList().get(i));
            }
        }

        // 收集Top出场
        Collections.sort(clubStatistics.getPlayerList(), new Comparator<PlayerDto>() {
            @Override
            public int compare(PlayerDto o1, PlayerDto o2) {
                return o2.getAppearance().compareTo(o1.getAppearance());
            }
        });
        for (int i = 0; i < min(3, clubStatistics.getPlayerList().size()); i++)
        {
            if (clubStatistics.getPlayerList().get(i).getAppearance().compareTo(0L) > 0)
            {
                clubStatistics.getTopPlayer().add(clubStatistics.getPlayerList().get(i));
            }
        }

        // 收集Top助攻
        Collections.sort(clubStatistics.getPlayerList(), new Comparator<PlayerDto>() {
            @Override
            public int compare(PlayerDto o1, PlayerDto o2) {
                return o2.getAssist().compareTo(o1.getAssist());
            }
        });
        for (int i = 0; i < min(3, clubStatistics.getPlayerList().size()); i++)
        {
            if (clubStatistics.getPlayerList().get(i).getAssist().compareTo(0L) > 0)
            {
                clubStatistics.getTopAssister().add(clubStatistics.getPlayerList().get(i));
            }
        }

        return new ResponseResult(200, "成功", clubStatistics);
    }

    @Override
    public ResponseResult getPlayerStatistics(Long year, String playerId) {
        // 获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userId = loginUser.getUser().getId();

        // 获取当前俱乐部ID
        PlayerLastClub playerLastClub = playerLastClubMapper.selectOne(new QueryWrapper<PlayerLastClub>().eq("player_id", userId));
        String clubId = playerLastClub.getLastClubId();

        // 校验查询的成员是否属于该俱乐部
        ClubPlayer clubPlayer = clubPlayerMapper.selectOne(new QueryWrapper<ClubPlayer>().eq("player_id", playerId).eq("club_id", clubId));
        if (Objects.isNull(clubPlayer)) {
            return new ResponseResult(457, "该球员不属于本俱乐部");
        }

        // 统计球员数据
        List<GamePlayer> gamePlayerList = gamePlayerMapper.selectAllGame(year, clubId, playerId);
        //System.out.println(gamePlayerList.size());

        PlayerStatisticsDto playerStatisticsDto = new PlayerStatisticsDto();
        User player = userMapper.selectById(playerId);
        playerStatisticsDto.setPlayerId(playerId);
        playerStatisticsDto.setPlayerName(player.getUsername());

        for (GamePlayer gamePlayer : gamePlayerList)
        {
            playerStatisticsDto.setAppearance(playerStatisticsDto.getAppearance() + 1);
            Game game = gameMapper.selectById(gamePlayer.getGameId());
            if (game.getOurScore().compareTo(game.getOpponentScore()) > 0)
            {
                playerStatisticsDto.setWin(playerStatisticsDto.getWin() + 1);
            } else if (game.getOurScore().compareTo(game.getOpponentScore()) == 0)
            {
                playerStatisticsDto.setTie(playerStatisticsDto.getTie() + 1);
            } else
            {
                playerStatisticsDto.setLose(playerStatisticsDto.getLose() + 1);
            }

            playerStatisticsDto.setGoal(playerStatisticsDto.getGoal() + gamePlayer.getGoal());
            playerStatisticsDto.setAssist(playerStatisticsDto.getAssist() + gamePlayer.getAssist());

            if (gamePlayer.getIsMVP())
            {
                playerStatisticsDto.setMvp(playerStatisticsDto.getMvp() + 1);
            }
        }
        return new ResponseResult(200, "成功", playerStatisticsDto);
    }

    @Override
    public Game getGameById(String gameId) {
        return gameMapper.selectById(gameId);
    }
}
