package com.fuint.common.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuint.common.Constants;
import com.fuint.common.dto.*;
import com.fuint.common.enums.PrizeTypeEnum;
import com.fuint.common.enums.RaffleTypeEnum;
import com.fuint.common.enums.StatusEnum;
import com.fuint.common.enums.WxMessageEnum;
import com.fuint.common.param.RaffleParam;
import com.fuint.common.service.*;
import com.fuint.common.util.DateUtil;
import com.fuint.framework.annoation.OperationServiceLog;
import com.fuint.framework.exception.BusinessCheckException;
import com.fuint.framework.pagination.PaginationRequest;
import com.fuint.framework.pagination.PaginationResponse;
import com.fuint.framework.web.ResponseObject;
import com.fuint.module.clientApi.controller.ClientRaffleController;
import com.fuint.repository.mapper.MtPointMapper;
import com.fuint.repository.mapper.MtRaffleItemMapper;
import com.fuint.repository.mapper.MtRaffleMapper;
import com.fuint.repository.mapper.MtUserMapper;
import com.fuint.repository.model.*;
import com.fuint.utils.StringUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 积分管理业务实现类
 *
 * Created by FSQ
 * CopyRight https://www.fuint.cn
 */
@Service
public class RaffleServiceImpl extends ServiceImpl<MtRaffleMapper, MtRaffle> implements RaffleService {

    private static final Logger logger = LoggerFactory.getLogger(RaffleServiceImpl.class);

    @Resource
    private MtRaffleMapper mtRaffleMapper;
    @Resource
    private MtRaffleItemMapper mtRaffleItemMapper;
    @Resource
    private MtUserMapper mtUserMapper;
    @Resource
    private PointService pointService;
    @Autowired
    private SettingService settingService;
    @Resource
    private BalanceService balanceService;

    /**
     * 分页查询积分列表
     *
     * @param paginationRequest
     * @return
     */
    @Override
    public PaginationResponse<RaffleDto> queryListByPagination(PaginationRequest paginationRequest) throws BusinessCheckException {
        Page<MtPoint> pageHelper = PageHelper.startPage(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
        LambdaQueryWrapper<MtRaffle> lambdaQueryWrapper = Wrappers.lambdaQuery();
        String status = paginationRequest.getSearchParams().get("status") == null ? "" : paginationRequest.getSearchParams().get("status").toString();
        String title = paginationRequest.getSearchParams().get("title") == null ? "" : paginationRequest.getSearchParams().get("title").toString();
        if (StringUtils.isNotBlank(status)) {
            lambdaQueryWrapper.eq(MtRaffle::getStatus, status);
        }
        if (StringUtils.isNotBlank(title)) {
            lambdaQueryWrapper.like(MtRaffle::getTitle, title);
        }
        lambdaQueryWrapper.orderByDesc(MtRaffle::getCreateTime);
        List<MtRaffle> raffleList = mtRaffleMapper.selectList(lambdaQueryWrapper);

        List<RaffleDto> dataList = new ArrayList<>();
        for (MtRaffle raffle : raffleList) {
            RaffleDto item = new RaffleDto();
            item.setId(raffle.getId());
            item.setBrief(raffle.getBrief());
            item.setTitle(raffle.getTitle());
            item.setDescription(raffle.getDescription());
            item.setRafflePoint(raffle.getRafflePoint());
            item.setImage(raffle.getImage());
            item.setRaffleType(raffle.getRaffleType());
            item.setClick(raffle.getClick());
            item.setHot(raffle.getHot());
            item.setSort(raffle.getSort());
            item.setNowCnt(raffle.getNowCnt());
            item.setAllCnt(raffle.getAllCnt());
            item.setDescription(raffle.getDescription());
            item.setCreateTime(raffle.getCreateTime());
            item.setUpdateTime(raffle.getUpdateTime());
            item.setOperator(raffle.getOperator());
            item.setStatus(raffle.getStatus());
            dataList.add(item);
        }


        PageRequest pageRequest = PageRequest.of(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
        PageImpl pageImpl = new PageImpl(dataList, pageRequest, pageHelper.getTotal());
        PaginationResponse<RaffleDto> paginationResponse = new PaginationResponse(pageImpl, RaffleDto.class);
        paginationResponse.setTotalPages(pageHelper.getPages());
        paginationResponse.setTotalElements(pageHelper.getTotal());
        paginationResponse.setContent(dataList);

        return paginationResponse;
    }

    @Override
    public int addRaffle(MtRaffle reqRaffleDto) throws BusinessCheckException {

        return mtRaffleMapper.insertForId(reqRaffleDto);
    }

    @Override
    public void addRaffleItem(MtRaffleItem reqRaffleItemDto) throws BusinessCheckException {
        mtRaffleItemMapper.insert(reqRaffleItemDto);
    }

    @Override
    public List<MtRaffleItem> queryRaffleItemByRaffleId(RaffleItemDto raffleItemDto) throws BusinessCheckException {
        LambdaQueryWrapper<MtRaffleItem> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffleItem::getRaffleId, raffleItemDto.getRaffleId());

        if (raffleItemDto.getUserId() != null) {
            lambdaQueryWrapper.eq(MtRaffleItem::getUserId, raffleItemDto.getUserId());
        }
        if (raffleItemDto.getWin() != null) {
            lambdaQueryWrapper.eq(MtRaffleItem::getWin, raffleItemDto.getWin());
        }
        if (raffleItemDto.getDeal() != null) {
            lambdaQueryWrapper.eq(MtRaffleItem::getDeal,raffleItemDto.getDeal());
        }
        if (raffleItemDto.getUserNo() != null) {
            lambdaQueryWrapper.eq(MtRaffleItem::getUserNo,raffleItemDto.getUserNo());
        }

        List<MtRaffleItem> raffleList = mtRaffleItemMapper.selectList(lambdaQueryWrapper);
        
        return raffleList;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<MtRaffleItem> doRaffleByRaffleId(Integer raffleId, Integer num, UserInfo userinfo, Integer forwardUserId) throws BusinessCheckException {

        MtUser user = mtUserMapper.selectById(userinfo.getId());

        //获取抽奖信息
        MtRaffle mtRaffle = mtRaffleMapper.selectById(raffleId);
        mtRaffle.setNowCnt(mtRaffle.getNowCnt()+num);
        mtRaffleMapper.updateById(mtRaffle);

        LambdaQueryWrapper<MtRaffleItem> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffleItem::getRaffleId, raffleId);
        lambdaQueryWrapper.eq(MtRaffleItem::getWin, 0); //奖品状态 1已抽中 0未抽中
        List<MtRaffleItem> raffleList = mtRaffleItemMapper.selectList(lambdaQueryWrapper);

        //扣减积分
        MtPoint mtPoint = new MtPoint();
        mtPoint.setUserId(user.getId());
        mtPoint.setAmount(mtRaffle.getRafflePoint()*-1*num);
        mtPoint.setDescription("一番赏："+mtRaffle.getTitle()+ "/" + num+"次");
        pointService.addPoint(mtPoint);

        //更新中奖信息
        String baseImage = settingService.getUploadBasePath();

        List<MtRaffleItem> resultList = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            int removeNum = new Random().nextInt(raffleList.size());
            MtRaffleItem mtRaffleItem = raffleList.get(removeNum);
            mtRaffleItem.setUserId(user.getId());
            mtRaffleItem.setUserNo(user.getUserNo());
            mtRaffleItem.setWin(1);//奖品状态 1已抽中 0未抽中
            mtRaffleItem.setName(user.getName());
            mtRaffleItem.setUpdateTime(new Date());
            mtRaffleItem.setForwardUserId(forwardUserId);
            mtRaffleItemMapper.updateById(mtRaffleItem);
            mtRaffleItem.setImage(baseImage + mtRaffleItem.getImage());
            raffleList.remove(removeNum);
            resultList.add(mtRaffleItem);
        }
        //判断额外奖是随机还是最终
        List<MtRaffleItem> count = mtRaffleItemMapper.selectList(lambdaQueryWrapper);
        if (count.size() == 0 && StringUtil.isNotEmpty(mtRaffle.getExtraPrize())) {

            logger.info(mtRaffle.getTitle()+"抽完准备出赏");

            MtRaffleItem extraItem = new MtRaffleItem();
            extraItem.setTitle(mtRaffle.getTitle());
            extraItem.setPrize(mtRaffle.getExtraPrize());
            extraItem.setImage(mtRaffle.getExtraImage());
            extraItem.setPoint(mtRaffle.getRafflePoint());
            extraItem.setRaffleId(mtRaffle.getId());
            extraItem.setUserId(user.getId());
            extraItem.setUserNo(user.getUserNo());
            extraItem.setName(user.getName());
            extraItem.setWin(1);//奖品状态 1已抽中 0未抽中
            extraItem.setPrizeType(PrizeTypeEnum.EXTRA.getKey());

            extraItem.setUpdateTime(new Date());
            if ("L".equals(mtRaffle.getExtraType())) {
                extraItem.setUserId(user.getId());
                extraItem.setUserNo(user.getUserNo());
                extraItem.setName(user.getName());
                logger.info(mtRaffle.getTitle()+"最后出赏");
            } else if ("R".equals(mtRaffle.getExtraType())) {
                List<Integer> userIdlist = mtRaffleItemMapper.queryUserIdByRaffleId(mtRaffle.getId());
                logger.info(mtRaffle.getTitle()+"随机出赏");
                logger.info("随机用户ID：" + JSONArray.toJSONString(userIdlist));
                Integer userId = userIdlist.get(new Random().nextInt(userIdlist.size()));
                MtUser extraUser = mtUserMapper.selectById(userId);

                extraItem.setUserId(extraUser.getId());
                extraItem.setUserNo(extraUser.getUserNo());
                extraItem.setName(extraUser.getName());
            }
            mtRaffleItemMapper.insert(extraItem);

        }
        //转发奖励积分
        if (forwardUserId > 0 && forwardUserId != user.getId() && mtRaffle.getForwardPoint() > 0) {
            MtPoint forwardUser = new MtPoint();
            forwardUser.setUserId(forwardUserId);
            forwardUser.setAmount(mtRaffle.getForwardPoint()*num);
            forwardUser.setDescription("推广一番赏："+mtRaffle.getTitle()+ "/" + num+"次，转发奖励："+forwardUser.getAmount()+"积分");
            pointService.addPoint(forwardUser);


//            MtBalance dto = new MtBalance();
//            dto.setUserId(forwardUserId);
//            dto.setAmount(BigDecimal.valueOf(mtRaffle.getForwardPoint()*num));
//            dto.setDescription("推广一番赏："+mtRaffle.getTitle()+ "/" + num+"次，转发奖励:"+dto.getAmount());
//            dto.setOperator("system");
//            balanceService.addBalance(dto);
        }

        return resultList;
    }

    @Override
    public ResponseObject findRaffleList(RaffleParam raffleParam) throws BusinessCheckException {
        Integer pageNumber = raffleParam.getPage() == null ? Constants.PAGE_NUMBER : raffleParam.getPage();
        Integer pageSize = raffleParam.getPageSize() == null ? Constants.PAGE_SIZE : raffleParam.getPageSize();
        String dataType = raffleParam.getDataType() == null ? null : raffleParam.getDataType();

        Page<MtPoint> pageHelper = PageHelper.startPage(pageNumber, pageSize);
        LambdaQueryWrapper<MtRaffle> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffle::getStatus, StatusEnum.ENABLED.getKey());
        if (dataType != null && !RaffleTypeEnum.ALL.getKey().equals(dataType)) {
            lambdaQueryWrapper.eq(MtRaffle::getRaffleType, dataType);
        }
        lambdaQueryWrapper.orderByDesc(MtRaffle::getCreateTime);
        String baseImage = settingService.getUploadBasePath();
        List<MtRaffle> raffleList = mtRaffleMapper.selectList(lambdaQueryWrapper);
        List<RaffleDto> resultList = new ArrayList<>();
        for (MtRaffle raffle:raffleList) {
            RaffleDto dto = new RaffleDto();
            BeanUtils.copyProperties(raffle, dto);
            dto.setImage(baseImage+raffle.getImage());
            if (raffle.getExtraImage() != null) {
                dto.setExtraImage(baseImage + raffle.getExtraImage());
            }
            resultList.add(dto);
        }

        PageRequest pageRequest = PageRequest.of(pageNumber, pageSize);
        PageImpl pageImpl = new PageImpl(resultList, pageRequest, pageHelper.getTotal());
        PaginationResponse<RaffleDto> paginationResponse = new PaginationResponse(pageImpl, RaffleDto.class);
        paginationResponse.setTotalPages(pageHelper.getPages());
        paginationResponse.setTotalElements(pageHelper.getTotal());
        paginationResponse.setContent(resultList);

        return new ResponseObject(200, "查询成功", paginationResponse);
    }

    @Override
    public MtRaffle queryRaffle(Integer raffleId) throws BusinessCheckException {
        String baseImage = settingService.getUploadBasePath();

        MtRaffle raffle = mtRaffleMapper.selectById(raffleId);
        raffle.setImage(baseImage+raffle.getImage());
        raffle.setExtraImage(baseImage+raffle.getExtraImage());
        return raffle;
    }

    @Override
    public int updRaffle(MtRaffle reqRaffleDto) throws BusinessCheckException {

        return mtRaffleMapper.updateById(reqRaffleDto);

    }

    @Override
    public List<RaffleItemDto> queryRaffleItemByUserId(Integer userId) throws BusinessCheckException {
        LambdaQueryWrapper<MtRaffleItem> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffleItem::getUserId, userId);
        lambdaQueryWrapper.eq(MtRaffleItem::getWin,1); //1：已抽中
        lambdaQueryWrapper.eq(MtRaffleItem::getDeal,0);//0：未处理
        lambdaQueryWrapper.orderByDesc(MtRaffleItem::getCreateTime);
        List<MtRaffleItem> raffleList = mtRaffleItemMapper.selectList(lambdaQueryWrapper);

        String baseImage = settingService.getUploadBasePath();
        List<RaffleItemDto> resultList = new ArrayList<>();
        for (MtRaffleItem raffle:raffleList) {
            RaffleItemDto dto = new RaffleItemDto();
            BeanUtils.copyProperties(raffle, dto);
            dto.setImage(baseImage+raffle.getImage());
            resultList.add(dto);
        }


        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean tranfer2Point(Integer raffleItemId, Integer userId) throws BusinessCheckException {

        MtUser user = mtUserMapper.selectById(userId);

        MtRaffleItem item = mtRaffleItemMapper.selectById(raffleItemId);
        //已转化积分或者已领取
        if (item.getDeal() == 1) {
            return false;
        }
        MtPoint mtPoint = new MtPoint();
        mtPoint.setUserId(user.getId());
        mtPoint.setAmount(item.getPoint());
        mtPoint.setDescription("转化积分："+item.getTitle());
        pointService.addPoint(mtPoint);

        item.setDeal(1); //1:已处理，2：未处理
        item.setUpdateTime(new Date());
        item.setOperator("操作人：" + userId);
        mtRaffleItemMapper.updateById(item);

        return true;

    }

    @Override
    public Integer userPoint(Integer userId) throws BusinessCheckException {
        MtUser user = mtUserMapper.selectById(userId);
        return user.getPoint();
    }

    @Override
    public boolean dealRaffleItem(Integer raffleItemId, String name) throws BusinessCheckException {

        MtRaffleItem item = new MtRaffleItem();
        item.setId(raffleItemId);
        item.setDeal(1);
        item.setOperator("操作人：" + name);
        mtRaffleItemMapper.updateById(item);

        return true;
    }

    @Override
    public List<RaffleDto> getLatestRaffles(Integer limit) throws BusinessCheckException {
        int size = (limit == null || limit <= 0) ? 5 : limit;
        LambdaQueryWrapper<MtRaffle> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffle::getStatus, StatusEnum.ENABLED.getKey());
        lambdaQueryWrapper.orderByDesc(MtRaffle::getCreateTime);
        lambdaQueryWrapper.last("limit " + size);

        String baseImage = settingService.getUploadBasePath();
        List<MtRaffle> raffleList = mtRaffleMapper.selectList(lambdaQueryWrapper);
        List<RaffleDto> resultList = new ArrayList<>();
        for (MtRaffle raffle : raffleList) {
            RaffleDto dto = new RaffleDto();
            BeanUtils.copyProperties(raffle, dto);
            dto.setImage(baseImage + raffle.getImage());
            if (raffle.getExtraImage() != null) {
                dto.setExtraImage(baseImage + raffle.getExtraImage());
            }
            resultList.add(dto);
        }
        return resultList;
    }

    @Override
    public List<RaffleItemDto> getLatestWinItems(Integer limit) throws BusinessCheckException {
        int size = (limit == null || limit <= 0) ? 20 : limit;
        LambdaQueryWrapper<MtRaffleItem> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffleItem::getWin, 1);
        lambdaQueryWrapper.orderByDesc(MtRaffleItem::getCreateTime);
        lambdaQueryWrapper.last("limit " + size);

        String baseImage = settingService.getUploadBasePath();
        List<MtRaffleItem> raffleList = mtRaffleItemMapper.selectList(lambdaQueryWrapper);
        List<RaffleItemDto> resultList = new ArrayList<>();
        for (MtRaffleItem raffle : raffleList) {
            RaffleItemDto dto = new RaffleItemDto();
            BeanUtils.copyProperties(raffle, dto);
            dto.setImage(baseImage + raffle.getImage());
            resultList.add(dto);
        }
        return resultList;
    }

    @Override
    public List<RaffleItemDto> queryRaffleItemByRaffleId2wechat(Integer raffleId) throws BusinessCheckException {
        LambdaQueryWrapper<MtRaffleItem> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(MtRaffleItem::getRaffleId, raffleId);
        lambdaQueryWrapper.eq(MtRaffleItem::getPrizeType, PrizeTypeEnum.NORMAL.getKey());
        List<MtRaffleItem> raffleList = mtRaffleItemMapper.selectList(lambdaQueryWrapper);
        List<RaffleItemDto> resultList = new ArrayList<>();

        String baseImage = settingService.getUploadBasePath();

        for (MtRaffleItem mtRaffleItem:raffleList) {
            RaffleItemDto dto = new RaffleItemDto();
            BeanUtils.copyProperties(mtRaffleItem, dto);
            dto.setImage(baseImage+mtRaffleItem.getImage());
            resultList.add(dto);
        }

        return resultList;
    }
}
