package com.td.Dawa.game.comcharacters.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import com.td.Dawa.annotation.In;
import com.td.Dawa.common.service.*;
import com.td.Dawa.config.enums.GameEnum;
import com.td.Dawa.game.comcharacters.pojo.ComCharacters;
import com.td.Dawa.game.comcharacters.vo.ComCharactersClientVo;
import com.td.Dawa.game.comcharacters.vo.ComCharactersRandomVo;
import com.td.Dawa.game.comcharacters.vo.ComCharactersVo;
import com.td.Dawa.game.comcharacters.repository.ComCharactersRepository;
import com.td.Dawa.game.excelcharacterattri.pojo.ExcelCharacterAttri;
import com.td.Dawa.game.excelcharacterattri.repository.ExcelCharacterAttriRepository;
import com.td.Dawa.game.excelcharacterattri.service.ExcelCharacterAttriService;
import com.td.Dawa.game.excelcharacterattri.vo.ExcelCharacterAttriVo;
import com.td.Dawa.game.excelcharactercolor.pojo.ExcelCharacterColor;
import com.td.Dawa.game.excelcharactercolor.service.ExcelCharacterColorService;
import com.td.Dawa.game.excelcharactercolor.vo.ExcelCharacterColorClientVo;
import com.td.Dawa.game.excelcharactercreate.pojo.ExcelCharacterCreate;
import com.td.Dawa.game.excelcharactercreate.service.ExcelCharacterCreateService;
import com.td.Dawa.game.excelcharactercreate.vo.ExcelCharacterCreateClientVo;
import com.td.Dawa.game.excelcharacterlevel.service.ExcelCharacterLevelService;
import com.td.Dawa.game.excelcharacterlevel.vo.ExcelCharacterLevelVo;
import com.td.Dawa.game.excelresources.service.ExcelResourcesService;
import com.td.Dawa.game.excelresources.vo.ExcelResourcesClientVo;
import com.td.Dawa.util.CopyUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.query.criteria.internal.CriteriaBuilderImpl;
import org.hibernate.query.criteria.internal.expression.function.BasicFunctionExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.Expression;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class ComCharactersServiceImpl extends CommonServiceImpl<ComCharactersVo, ComCharacters, Integer> implements ComCharactersService {

    @PersistenceContext
    private EntityManager em;
    @Autowired
    private ComCharactersRepository comCharactersRepository;

    @Autowired
    private ExcelCharacterAttriRepository excelCharacterAttriRepository;

    /**
     * excel表service
     */
    @Autowired
    private ExcelCharacterCreateService excelCharacterCreateService;

    @Autowired
    private ExcelCharacterAttriService excelCharacterAttriService;

    @Autowired
    private ExcelCharacterLevelService excelCharacterLevelService;

    @Autowired
    private ExcelCharacterColorService excelCharacterColorService;

    @Autowired
    private ExcelResourcesService excelResourcesService;


    @Override
    public List<ComCharactersRandomVo> randomRoleByNumber(Integer number) {
        Specification<ExcelCharacterAttri> specification = (root, query, cb) -> {
            //Predicate pd = cb.and(cb.equal(root.get("title"), "测试题"));
            Expression<Double> e = new BasicFunctionExpression<>(
                    (CriteriaBuilderImpl) cb, Double.class, "rand"
            );
            query.orderBy(cb.desc(e));
            return null;
        };
        //1.获取了number 数量的 roleType todo 可加入内存
        List<ExcelCharacterAttri> excelCharacterAttrList = excelCharacterAttriRepository.findAll(specification, PageRequest.of(0, number)).toList();
        //2.根据roleType分类
        List<ComCharactersRandomVo> characters = new ArrayList<>();
        //3.查询role表全部数据
        //List<Integer> roleIds = excelCharacterAttrList.stream().map(e -> e.getRoleType()).collect(Collectors.toList());
        for (ExcelCharacterAttri excelCharacterAttr : excelCharacterAttrList) {
            ComCharactersRandomVo character = new ComCharactersRandomVo();
            character.setRoleId(excelCharacterAttr.getId());
            character.setRoleType(excelCharacterAttr.getRoleType());
            character.setAction(excelCharacterAttr.getAction());
            character.setInteractive(excelCharacterAttr.getInteractive());
            characters.add(character);
        }
        return characters;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ComCharactersClientVo addRole(ExcelCharacterAttriVo _attr, String userId) {

        Integer roleType = _attr.getRoleType();//todo 暂时用属性表里面的roleType
        //1.添加一个角色
        ComCharacters comCharacters = new ComCharacters();
        comCharacters.setUserId(userId);
        comCharacters.setRoleId(_attr.getId()); //用属性的id来设置roleId
        comCharacters.setRoleType(roleType);
        ////力量
        //Double _powerDouble = new Random().nextDouble() * (_attr.getStartPowerLimitUpper() - _attr.getStartPowerLimitLower()) + _attr.getStartPowerLimitLower();
        //comCharacters.setPower(_powerDouble.intValue());
        ////智力(智慧)
        //Double _intelligenceDouble = new Random().nextDouble() * (_attr.getStartWisdomLimitUpper() - _attr.getStartWisdomLimitLower()) + _attr.getStartWisdomLimitLower();
        //comCharacters.setIntelligence(_intelligenceDouble.intValue());
        ////技巧
        //Double _skillsDouble = new Random().nextDouble() * (_attr.getStartSkillLimitUpper() - _attr.getStartSkillLimitLower()) + _attr.getStartSkillLimitLower();
        //comCharacters.setSkills(_skillsDouble.intValue());

        //随机一个力量值，添加到后面的属性上
        Double _random = new Random().nextDouble() * _attr.getRandomAttr();
        comCharacters.setRandom(_random.intValue());

        //力量
        Double _powerDouble = _random + _attr.getStartPowerLimitLower();
        comCharacters.setPower(_powerDouble.intValue());
        //智力(智慧)
        Double _intelligenceDouble = _random + _attr.getStartWisdomLimitLower();
        comCharacters.setIntelligence(_intelligenceDouble.intValue());
        //技巧
        Double _skillsDouble = _random + _attr.getStartSkillLimitLower();
        comCharacters.setSkills(_skillsDouble.intValue());


        String[] itemArray = _attr.getProfessional().split("\\|");

        int a = (int) Math.floor(new Random().nextDouble() * itemArray.length);
        comCharacters.setProfessional(Integer.parseInt(itemArray[a]));

        comCharacters.setAction(_attr.getAction());

        comCharacters.setInteractive(_attr.getInteractive());
        comCharacters.setState(0);

        //随机生成一套model,todo 暂时固定7个,

        List<ExcelCharacterColor> colorListVo = new ArrayList<>();
        List<String> colorIdList = new ArrayList<>();
        //全部颜色
        List<ExcelCharacterColor> characterColorList = excelCharacterColorService.getListFromCache(GameEnum.REDIS_KEY_EXCEL_CHARACTER_COLOR.getMessage());
        List<ExcelCharacterCreate> _list = excelCharacterCreateService.findAll();
        List<ExcelCharacterCreate> _genList = generateCharacterModels(_list);
        List<String> modelList = _genList.stream().map(e -> {
            //创建对应的颜色
            ExcelCharacterColor _color = characterColorList.get((int) (Math.random() * characterColorList.size()));
            colorListVo.add(_color);
            colorIdList.add(_color.getId().toString());
            return e.getModel().toString();
        }).collect(Collectors.toList());
        comCharacters.setModelId(String.join("|", modelList));
        //记录颜色id
        comCharacters.setModelColor(String.join("|", colorIdList));

        //设置经验和等级
        comCharacters.setExp(0);
        comCharacters.setLevel(1);
        //todo 需要扣除对应金币

        comCharacters.setCreateTime(DateUtil.date());
        comCharacters.setUpdateTime(DateUtil.date());
        comCharacters = comCharactersRepository.saveAndFlush(comCharacters);
        //再存储一次id，根据当前生成的角色自增id来作为名字
        comCharacters.setName(comCharacters.getId().toString());
        comCharactersRepository.save(comCharacters);

        ComCharactersClientVo clientVo = CopyUtil.copy(comCharacters, ComCharactersClientVo.class);
        //设置第二级的升级经验
        ExcelCharacterLevelVo excelCharacterLevelVo = excelCharacterLevelService.getVo(2);
        clientVo.setLevelUpExp(excelCharacterLevelVo.getExp());
        //clientVo.setSubCreateClientList(CopyUtil.copyList(_list, ExcelCharacterCreateClientVo.class));
        //对应资源
        Integer[] _modelIdArray = Convert.toIntArray(comCharacters.getModelId().split("\\|"));
        final int[] index = {0};
        List<ExcelResourcesClientVo> resourcesList = excelResourcesService.findByArtIdIn(_modelIdArray).stream().map(_res -> {
            ExcelCharacterCreate excelCharacterCreate = _genList.stream().filter(_gen -> _gen.getModel().equals(_res.getArtId())).findFirst().get();

            _res.setPosition(excelCharacterCreate.getPosition());
            _res.setCharacterColor(CopyUtil.copy(colorListVo.get(index[0]), ExcelCharacterColorClientVo.class));
            index[0]++;
            log.info(index[0] + "");
            return _res;
        }).collect(Collectors.toList());
        clientVo.setSubResourcesClientList(resourcesList);

        return clientVo;
    }


    @Override
    public ComCharacters findByRoleId(Integer roleId) {
        return comCharactersRepository.findByRoleId(roleId).orElse(null);
    }


    @Override
    public List<ComCharactersClientVo> findByProfessionalSort(String userId, Integer professional) {
        String _properties = "power";//默认power排序
        if (professional.equals(GameEnum.PRO_POWER.getValue())) {
            _properties = "power";
        } else if (professional.equals(GameEnum.PRO_INTELLIGENCE.getValue())) {
            _properties = "intelligence";
        } else if (professional.equals(GameEnum.PRO_SKIlLS.getValue())) {
            _properties = "skills";
        }
        List<ComCharacters> comCharactersList = comCharactersRepository.findByUserIdAndProfessional(userId, professional, Sort.by(Sort.Direction.DESC, _properties));
        List<ComCharactersClientVo> comCharactersClientVos = comCharactersList.stream().map(e -> {
            ComCharactersClientVo comCharactersClientVo = new ComCharactersClientVo();
            comCharactersClientVo = CopyUtil.copy(e, ComCharactersClientVo.class);
            comCharactersClientVo = addSubResourcesClientListToVO(comCharactersClientVo, e.getModelId(), e.getModelColor());
            //Integer[] _modelIdArray = Convert.toIntArray(e.getModelId().split("\\|"));
            ////查询position
            //List<ExcelCharacterCreate> _genList =  excelCharacterCreateService.findByModelIn(_modelIdArray);
            //List<ExcelResourcesClientVo> resourcesList = excelResourcesService.findByArtIdIn(_modelIdArray).stream().map(_res->{
            //    ExcelCharacterCreate excelCharacterCreate = _genList.stream().filter(_gen->_gen.getModel().equals(_res.getArtId())).findFirst().get();
            //    _res.setPosition(excelCharacterCreate.getPosition());
            //    return _res;
            //}).collect(Collectors.toList());
            //comCharactersClientVo.setSubResourcesClientList(resourcesList);
            return comCharactersClientVo;
        }).collect(Collectors.toList());
        return comCharactersClientVos;
    }


    @Override
    public List<ComCharacters> findByRoleIdIn(Integer[] ids) {
        return comCharactersRepository.findByIdIn(ids, Sort.by(Sort.Direction.ASC, "id"));
    }

    /**
     * 生成 7个配件
     *
     * @param _allList
     * @return
     */
    private List<ExcelCharacterCreate> generateCharacterModels(List<ExcelCharacterCreate> _allList) {
        List<ExcelCharacterCreate> _currentCharacters = new ArrayList<>();
        //1.生成瞳孔
        //权重计算，当前有20个权重1,9个权重6,4个权重5，加起来值是100
        List<ExcelCharacterCreate> pupilAll = _allList.stream().filter(e -> e.getPosition().equals(1)).collect(Collectors.toList());
        ExcelCharacterCreate pupil = pupilAll.get((int) (Math.random() * pupilAll.size()));
        //左右瞳孔 todo 颜色区分
        _currentCharacters.add(pupil);
        _currentCharacters.add(pupil);
        //2.生成耳朵
        List<ExcelCharacterCreate> earsAll = _allList.stream().filter(e -> e.getPosition().equals(2)).collect(Collectors.toList());
        ExcelCharacterCreate ears = earsAll.get((int) (Math.random() * earsAll.size()));
        _currentCharacters.add(ears);
        _currentCharacters.add(ears);

        //3.生成眉毛
        List<ExcelCharacterCreate> eyebrowAll = _allList.stream().filter(e -> e.getPosition().equals(3)).collect(Collectors.toList());
        ExcelCharacterCreate eyebrow = eyebrowAll.get((int) (Math.random() * eyebrowAll.size()));
        _currentCharacters.add(eyebrow);
        _currentCharacters.add(eyebrow);

        //4.生成吻部
        List<ExcelCharacterCreate> snoutAll = _allList.stream().filter(e -> e.getPosition().equals(4)).collect(Collectors.toList());
        ExcelCharacterCreate snout = snoutAll.get((int) (Math.random() * snoutAll.size()));
        _currentCharacters.add(snout);

        //5.生成花纹
        List<ExcelCharacterCreate> decorativePatternAll = _allList.stream().filter(e -> e.getPosition().equals(5)).collect(Collectors.toList());
        ExcelCharacterCreate decorativePattern = decorativePatternAll.get((int) (Math.random() * decorativePatternAll.size()));
        _currentCharacters.add(decorativePattern);

        //6.生成轮廓
        List<ExcelCharacterCreate> outLineAll = _allList.stream().filter(e -> e.getPosition().equals(6)).collect(Collectors.toList());
        ExcelCharacterCreate outLine = outLineAll.get((int) (Math.random() * outLineAll.size()));
        _currentCharacters.add(outLine);

        //7.生成尾巴
        List<ExcelCharacterCreate> tailAll = _allList.stream().filter(e -> e.getPosition().equals(7)).collect(Collectors.toList());
        ExcelCharacterCreate tail = tailAll.get((int) (Math.random() * tailAll.size()));
        _currentCharacters.add(tail);

        return _currentCharacters;
    }

    /**
     * 查询子配件,设置到 ComCharactersClientVo 里面
     *
     * @param comCharactersClientVo
     * @param _modelIdStr
     * @return
     */
    @Override
    public ComCharactersClientVo addSubResourcesClientListToVO(ComCharactersClientVo comCharactersClientVo, String _modelIdStr, String _modelColorStr) {
        Integer[] _modelIdArray = Convert.toIntArray(_modelIdStr.split("\\|"));
        //查询position
        List<ExcelCharacterCreate> _genList = excelCharacterCreateService.findByModelIn(_modelIdArray);

        List<ExcelCharacterColor> allColorList = excelCharacterColorService.getListFromCache(GameEnum.REDIS_KEY_EXCEL_CHARACTER_COLOR.getMessage());
        List<String> _colorList = Arrays.asList(_modelColorStr.split("\\|"));
        List<ExcelCharacterColor> allExcelProps = allColorList.stream().filter(e -> _colorList.contains(e.getId().toString())).collect(Collectors.toList());


        final int[] index = {0};
        List<ExcelResourcesClientVo> resourcesList = excelResourcesService.findByArtIdIn(_modelIdArray).stream().map(_res -> {
            ExcelCharacterCreate excelCharacterCreate = _genList.stream().filter(_gen -> _gen.getModel().equals(_res.getArtId())).findFirst().get();
            _res.setPosition(excelCharacterCreate.getPosition());

            _res.setCharacterColor(CopyUtil.copy(allExcelProps.get(index[0]), ExcelCharacterColorClientVo.class));
            index[0]++;
            return _res;
        }).collect(Collectors.toList());
        comCharactersClientVo.setSubResourcesClientList(resourcesList);
        return comCharactersClientVo;
    }
}
