package org.jeecg.modules.system.app.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.system.app.dto.*;
import org.jeecg.modules.system.app.entity.AppGame;
import org.jeecg.modules.system.app.entity.AppGamePriceRules;
import org.jeecg.modules.system.app.entity.AppGameSchedule;
import org.jeecg.modules.system.app.mapper.*;
import org.jeecg.modules.system.app.service.IAppGameService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.jeecg.common.constant.CommonConstant.SC_INTERNAL_SERVER_ERROR_500;

/**
 * @Description: 赛事表
 * @Author: jeecg-boot
 * @Date: 2025-07-03
 * @Version: V1.0
 */
@Service
public class AppGameServiceImpl extends ServiceImpl<AppGameMapper, AppGame> implements IAppGameService {
    @Resource
    private AppGamePriceRulesMapper rulesMapper;
    @Resource
    private AppGameScheduleMapper scheduleMapper;
    @Resource
    private AppSiteMapper siteMapper;

    @Autowired
    private AppGameMapper appGameMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;
    @Autowired
    private AppOrderMapper appOrderMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveWitchPriceRules(AppGameDTO gameDTO) {

        AppGameCuDTO gameCuDTO = gameDTO.getGame();
        AppGame game = new AppGame();
        BeanUtils.copyProperties(gameCuDTO, game);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        game.setOrgCode(sysUser.getOrgCode());
        game.setTenantId(sysUser.getOrgId());

        checkTime(gameCuDTO.getApplicationEndTime(),gameCuDTO.getStartTime(),gameCuDTO.getEndTime());
        int saveGameResult = baseMapper.insert(game);
        if (saveGameResult < 1) {
            throw new JeecgBootException("赛事信息保存失败");
        }
        gameDTO.getGamePriceRules().forEach(gameRuleDtos -> {
            AppGamePriceRules appGamePriceRules = new AppGamePriceRules();
            BeanUtils.copyProperties(gameRuleDtos, appGamePriceRules);
            appGamePriceRules.setGameId(game.getId());
            appGamePriceRules.setOrgCode(game.getOrgCode());
            appGamePriceRules.setTenantId(game.getTenantId());
            int savePriceResult = rulesMapper.insert(appGamePriceRules); // 保证每个操作都在事务中
            if (savePriceResult < 1) {
                throw new JeecgBootException("赛事价格规则保存失败");
            }
        });
        gameDTO.getScheduleDTOS().forEach(scheduleDTO -> {
            AppGameSchedule appGameSchedule = new AppGameSchedule();
            BeanUtils.copyProperties(scheduleDTO, appGameSchedule);
            appGameSchedule.setGameId(game.getId());
            appGameSchedule.setOrgCode(game.getOrgCode());
            appGameSchedule.setTenantId(game.getTenantId());
            int saveScheduleResult = scheduleMapper.insert(appGameSchedule);
            if (saveScheduleResult < 1) {
                throw new JeecgBootException("赛事安排保存失败");
            }
        });

        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editWitchPriceRules(AppGameDTO gameDTO) {
        AppGameCuDTO gameCuDTO = gameDTO.getGame();
        AppGame game = new AppGame();
        BeanUtils.copyProperties(gameCuDTO, game);
        AppGame dbGame = baseMapper.selectById(game.getId());
        if (null == dbGame) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);

        List<AppGameRuleDTO> byGameId = rulesMapper.findByGameId(dbGame.getId());
        if(byGameId==null||byGameId.isEmpty()){
            throw new JeecgBootException("该赛事的比赛项目与价格为空", SC_INTERNAL_SERVER_ERROR_500);
        }
        Long orderNum=  appOrderMapper.findByProductIds(byGameId);
        if (orderNum>0){
            throw new JeecgBootException("该赛事已存在报名不允许修改", SC_INTERNAL_SERVER_ERROR_500);
        }

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        checkPermission(sysUser,dbGame);
        game.setOrgCode(sysUser.getOrgCode());
        game.setTenantId(sysUser.getOrgId());
        checkTime(gameCuDTO.getApplicationEndTime(),gameCuDTO.getStartTime(),gameCuDTO.getEndTime());
        int updateGameResult = baseMapper.updateById(game);
        if (updateGameResult < 1) {
            throw new JeecgBootException("赛事信息保存失败");
        }
        if (StringUtils.isNotEmpty(gameDTO.getGamePriceRulesList())){
            if (gameDTO.getGamePriceRulesList().indexOf(",")>0){
                for (String id : gameDTO.getGamePriceRulesList().split(",")) {
                    int i =rulesMapper.updateByIdDel(id);
                    if (i<1){
                        throw new JeecgBootException("删除赛程安排失败");
                    }
                }
            }else {
                int i = rulesMapper.updateByIdDel(gameDTO.getGamePriceRulesList());
                if (i<1){
                    throw new JeecgBootException("删除赛程安排失败");
                }
            }

        }
        if (StringUtils.isNotEmpty(gameDTO.getScheduleDTOSList())){
            if (gameDTO.getScheduleDTOSList().indexOf(",")>0){
                for (String id : gameDTO.getScheduleDTOSList().split(",")) {
                    int i =  scheduleMapper.updateByIdDel(id);
                    if (i<1){
                        throw new JeecgBootException("删除比赛项目失败");
                    }
                }
            }else {
                int i =  scheduleMapper.updateByIdDel(gameDTO.getScheduleDTOSList());
                if (i<1){
                    throw new JeecgBootException("删除比赛项目失败");
                }
            }
        }
        gameDTO.getGamePriceRules().forEach(gameRuleDTO -> {
            AppGamePriceRules appGamePriceRules = new AppGamePriceRules();
            BeanUtils.copyProperties(gameRuleDTO, appGamePriceRules);
            appGamePriceRules.setGameId(game.getId());
            appGamePriceRules.setOrgCode(game.getOrgCode());
            appGamePriceRules.setTenantId(game.getTenantId());
            int savePriceResult =0;
            if (StringUtils.isNotEmpty(gameRuleDTO.getId())){
                savePriceResult = rulesMapper.updateById(appGamePriceRules);
            }else {
                savePriceResult = rulesMapper.insert(appGamePriceRules);
            }
            if (savePriceResult < 1) {
                throw new JeecgBootException("赛事价格规则保存失败");
            }

        });
        gameDTO.getScheduleDTOS().forEach(scheduleDTO -> {
            AppGameSchedule appGameSchedule = new AppGameSchedule();
            BeanUtils.copyProperties(scheduleDTO, appGameSchedule);
            appGameSchedule.setGameId(game.getId());
            appGameSchedule.setOrgCode(game.getOrgCode());
            appGameSchedule.setTenantId(game.getTenantId());
            int saveScheduleResult =0;
            if (StringUtils.isNotEmpty(scheduleDTO.getId())){
                saveScheduleResult = scheduleMapper.updateById(appGameSchedule);
            }else {
                saveScheduleResult = scheduleMapper.insert(appGameSchedule);
            }
            if (saveScheduleResult < 1) {
                throw new JeecgBootException("赛事安排保存失败");
            }
        });

        return Boolean.TRUE;
    }

    @Override
    public AppGameDTO queryWitchPriceRulesById(String id) {
        AppGame dbGame = baseMapper.selectById(id);
        if (null == dbGame) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
        AppGameCuDTO appGameCuDTO = new AppGameCuDTO();
        BeanUtils.copyProperties(dbGame, appGameCuDTO);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        checkPermission(sysUser,dbGame);
        List<AppGameRuleDTO> gameRuleDTOS = new ArrayList<>();
        rulesMapper.selectList(Wrappers.<AppGamePriceRules>lambdaQuery().eq(AppGamePriceRules::getGameId, id)).forEach(priceRules -> {
            AppGameRuleDTO priceRulesDTO = new AppGameRuleDTO();
            BeanUtils.copyProperties(priceRules, priceRulesDTO);
            gameRuleDTOS.add(priceRulesDTO);
        });
        List<AppGameScheduleDTO> scheduleDTOS = new ArrayList<>();
        scheduleMapper.selectList(Wrappers.<AppGameSchedule>lambdaQuery().eq(AppGameSchedule::getGameId, id)).forEach(schedule -> {
            AppGameScheduleDTO scheduleDTO = new AppGameScheduleDTO();
            BeanUtils.copyProperties(schedule, scheduleDTO);
            scheduleDTOS.add(scheduleDTO);
        });
        return new AppGameDTO(appGameCuDTO, gameRuleDTOS, scheduleDTOS);
    }

    @Override
    public Boolean deleteWitchPriceRulesById(String id) {
        AppGame dbGame = baseMapper.selectById(id);
        if (null == dbGame) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        checkPermission(sysUser, dbGame);
        int deleteGameResult = baseMapper.deleteById(id);
        if (deleteGameResult < 1) {
            throw new JeecgBootException("赛事信息删除失败");
        }
        int deletePriceResult = rulesMapper.delete(Wrappers.<AppGamePriceRules>lambdaQuery().eq(AppGamePriceRules::getGameId, id));
        if (deletePriceResult<1) throw new JeecgBootException("赛事价格规则删除失败", SC_INTERNAL_SERVER_ERROR_500);
        int deleteScheduleResult = scheduleMapper.delete(Wrappers.<AppGameSchedule>lambdaQuery().eq(AppGameSchedule::getGameId, id));
        if (deleteScheduleResult<1) throw new JeecgBootException("赛事安排删除失败", SC_INTERNAL_SERVER_ERROR_500);
        return Boolean.TRUE;
    }

    @Override
    public IPage<AppGameDTO> queryWitchPriceRulesPage(AppGamePageDTO dto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Page<AppGame> page = new Page<>(dto.getPageNo(), dto.getPageSize());
//        LambdaQueryWrapper<AppGame> wrapper = Wrappers.<AppGame>lambdaQuery()
//                .like(StringUtils.isNotBlank(dto.getName()), AppGame::getName, dto.getName());
//                .eq(AppGame::getOrgCode, loginUser.getOrgCode());
        dto.setOrgCode(loginUser.getOrgCode());
        IPage<AppGameDTO> pageGame = appGameMapper.findPage(page, dto);
        if (pageGame!=null&&!pageGame.getRecords().isEmpty()){
            for (AppGameDTO record : pageGame.getRecords()) {
                List<AppGameRuleDTO> priceRulesDTOList =  rulesMapper.findByGameId(record.getId());
                record.setGamePriceRules(priceRulesDTOList);
            }
        }
        return  pageGame;
    }


    /**
     * 校验权限
     *
     * @param sysUser
     * @param game
     */
    private void checkPermission(LoginUser sysUser, AppGame game) {
        if (!sysUser.getOrgCode().equals(game.getOrgCode()))
            throw new JeecgBootException("无权限操作", SC_INTERNAL_SERVER_ERROR_500);
    }

    private void checkTime(Date applicationEndTime,Date startTime,Date endTime){
        if (applicationEndTime==null){
            throw new JeecgBootException("赛事信息保存失败,报名截止时间不能为空");
        }
        if (startTime==null||endTime==null){
            throw new JeecgBootException("赛事信息保存失败,比赛时间不能为空");
        }
        LocalDate localDate = applicationEndTime.toInstant()
                .atZone(ZoneId.systemDefault()) // 使用系统默认时区
                .toLocalDate();
        LocalDate localDateStart = startTime.toInstant()
                .atZone(ZoneId.systemDefault()) // 使用系统默认时区
                .toLocalDate();
        boolean before = localDate.isBefore(localDateStart);
        if (!before) {
            throw new JeecgBootException("赛事信息保存失败,报名截止时间必须在比赛时间之前");
        }
    }
}
