package com.liquidnet.client.admin.zhengzai.smile.service.impl;


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.github.pagehelper.PageInfo;
import com.liquidnet.client.admin.common.core.domain.AjaxResult;
import com.liquidnet.client.admin.common.core.page.TableDataInfo;
import com.liquidnet.client.admin.common.utils.StringUtils;
import com.liquidnet.client.admin.zhengzai.smile.dto.*;
import com.liquidnet.client.admin.zhengzai.smile.service.ISmileShowService;
import com.liquidnet.client.admin.zhengzai.smile.utils.SmileRedisUtils;
import com.liquidnet.service.goblin.constant.SmileRedisConst;
import com.liquidnet.service.kylin.dao.TicketAndStatusDao;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.entity.KylinPerformanceStatus;
import com.liquidnet.service.kylin.entity.KylinPerformances;
import com.liquidnet.service.kylin.mapper.*;
import com.liquidnet.service.smile.entity.SmileAgent;
import com.liquidnet.service.smile.entity.SmilePrice;
import com.liquidnet.service.smile.entity.SmileSchool;
import com.liquidnet.service.smile.entity.SmileUser;
import com.liquidnet.service.smile.mapper.SmileAgentMapper;
import com.liquidnet.service.smile.mapper.SmilePriceMapper;
import com.liquidnet.service.smile.mapper.SmileSchoolMapper;
import com.liquidnet.service.smile.mapper.SmileUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2022-03-14
 */
@Slf4j
@Service
public class SmileShowServiceImpl extends ServiceImpl<SmileSchoolMapper, SmileSchool> implements ISmileShowService {

    @Autowired
    SmileRedisUtils smileRedisUtils;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    KylinPerformancesMapper kylinPerformancesMapper;

    @Autowired
    KylinOrderTicketRelationsMapper kylinOrderTicketRelationsMapper;

    @Autowired
    KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    SmileAgentMapper smileAgentMapper;

    @Autowired
    KylinTicketsMapper kylinTicketsMapper;

    @Autowired
    SmileUserMapper smileUserMapper;

    @Autowired
    SmilePriceMapper smilePriceMapper;

    @Autowired
    KylinPerformanceStatusMapper kylinPerformanceStatusMapper;

    @Autowired
    private KylinOrderTicketsMapper orderTicketsMapper;

    @Override
    public TableDataInfo listShow(SmileShowParam smileShowParam) {
        PageInfo<KylinPerformances> pageInfo;
        TableDataInfo rspData = new TableDataInfo();
        //查询所有代理的演出id
        List<KylinPerformances> kylinPerformancesList = kylinPerformancesMapper.selectPerIdByAgent();
        pageInfo = new PageInfo<>(kylinPerformancesList);
        List<ShowVo> showVoList = kylinPerformancesList.stream().map(kylinPerformances -> {
            ShowVo vo = new ShowVo();
            //演出id
            vo.setPerformancesId(kylinPerformances.getPerformancesId());
            //演出名称
            vo.setTitle(kylinPerformances.getTitle());
            //城市
            vo.setCityName(kylinPerformances.getCityName());
            //根据演出id  查询所有订单
            Map map = kylinOrderTicketsMapper.selectByPerformanceId(kylinPerformances.getPerformancesId());
            vo.setOpen(map != null ? (BigDecimal) (map.get("open")) : null);
            vo.setTotalSalePrice(map != null ? (BigDecimal) (map.get("price")) : null);
            //根据演出id查询销售代理
            List<Long> ordNum = kylinOrderTicketRelationsMapper.concatByAgentDed(kylinPerformances.getPerformancesId());
            vo.setTotalOutAgent(ordNum.stream().reduce(Long::sum).orElse(0L));
            //演出结束时间
            vo.setTimeEnd(kylinPerformances.getTimeEnd());
            //演出开始时间
            vo.setTimeStart(kylinPerformances.getTimeStart());

            //演出状态
            LambdaQueryWrapper<KylinPerformanceStatus> queryWrapper = Wrappers.lambdaQuery(KylinPerformanceStatus.class);
            queryWrapper.eq(KylinPerformanceStatus::getPerformanceId, kylinPerformances.getPerformancesId());
            vo.setShowStatus(kylinPerformanceStatusMapper.selectOne(queryWrapper).getStatus());

            //打款状态
            vo.setStatus(smileRedisUtils.getShowStatus(kylinPerformances.getPerformancesId()));

            //演出顺序
            vo.setComment(kylinPerformances.getComment());

            return vo;
        }).collect(Collectors.toList());
        rspData.setCode(0);
        rspData.setRows(showVoList);
        rspData.setTotal(pageInfo.getTotal());
        return rspData;
    }

    @Override
    public AjaxResult sort(ShowSort showSort) {

        //查询数据库是否又该顺序的演出
        kylinPerformancesMapper.updateComment(showSort.getSort());
        kylinPerformancesMapper.updateCommentByPer(showSort.getSort(), showSort.getPerformancesId());

        List<String> showIds = smileRedisUtils.getShowIds();
        showIds.remove(showSort.getPerformancesId());
        showIds.add(0,showSort.getPerformancesId());
        smileRedisUtils.setShowIds(showIds);

        /*//获取排序演出id
        List<String> collect = kylinPerformancesMapper.selectPerIdByAgent().stream().map(KylinPerformances::getPerformancesId).collect(Collectors.toList());
        String perId = StringUtils.join(collect, ",");
        //保存所有演出id带顺序
        smileRedisUtils.setShowIds(perId);*/
        log.info("redis show key:{}", showSort.getPerformancesId());
        return AjaxResult.success();
    }

    @Override
    public AjaxResult price(SmilePriceParam smilePriceParam) {
        SmilePrice smilePrice = new SmilePrice();
        BeanUtils.copyProperties(smilePriceParam, smilePrice);
        //查询演出状态
        AjaxResult showStatue = showStatue(smilePriceParam);
        if (showStatue != null) {
            return showStatue;
        }
        Integer status = smileRedisUtils.getShowPriceUid(smilePriceParam.getPerformancesId(), smilePriceParam.getUid());
        if (smilePriceParam.getStatus().equals(status)) {
            return AjaxResult.warn("不可重复打款");
        }
        if (smilePriceParam.getStatus().equals(0)) {
            //计算该用户的佣金
            Map userPerformance = orderTicketsMapper.getUserPerformanceByUidAndProId(smilePriceParam.getUid(), smilePriceParam.getPerformancesId());
            BigDecimal price = userPerformance.get("commiss") == null ? new BigDecimal(0) : new BigDecimal(userPerformance.get("commiss").toString());
            smilePrice.setPrice(price);
            smilePrice.setCreatedDate(LocalDateTime.now());
            smilePriceMapper.insert(smilePrice);
            smileRedisUtils.setPriceByUid(smilePriceParam.getPerformancesId(), smilePriceParam.getUid());
            //计算总营收
            BigDecimal userTotalPrice = smileRedisUtils.getUserTotalPrice(smilePriceParam.getUid());
            smileRedisUtils.setUserTotalPrice(smilePriceParam.getUid(), price.add(userTotalPrice));
        }
        return AjaxResult.success();
    }

    private AjaxResult showStatue(SmilePriceParam smilePriceParam) {
        LambdaQueryWrapper<KylinPerformances> queryWrapper = Wrappers.lambdaQuery(KylinPerformances.class);
        queryWrapper.eq(KylinPerformances::getPerformancesId, smilePriceParam.getPerformancesId());
        LocalDateTime timeEnd = kylinPerformancesMapper.selectOne(queryWrapper).getTimeEnd();
        if (timeEnd.isAfter(LocalDateTime.now())) {
            return AjaxResult.warn("演出尚未结束不能进行打款");
        }
        return null;
    }

    @Override
    public AjaxResult getShowById(String performancesId) {
        if (!StringUtils.isEmpty(performancesId)) {
            ShowVoById showVoById = new ShowVoById();
            //根据演出ID查询演出数据演出数据
            KylinPerformanceVo kylinPerformanceVo = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performancesId)), KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
            if (kylinPerformanceVo == null) {
                return AjaxResult.warn("演出未找到");
            }
            //票提集合  根据演出id查询票提id
            List<ShowAgentVo> showAgentVoList = new ArrayList<>();
            List<ShowTicketVo> showTicketVoList = new ArrayList<>();
            List<SmileAgent> smileAgents = getSmileAgentsByProId(performancesId);
            if (smileAgents == null) {
                return AjaxResult.warn("该演出未开启代理票种");
            }
            Map<String, SmileAgent> map = getSmileAgentMap(smileAgents);

            //代理票的id
            List<String> ticketsIdList = smileAgents.stream().map(SmileAgent::getTicketId).collect(Collectors.toList());

            if (ticketsIdList.size() > 0) {
                ShowTicketVo totalShowTicketVo = new ShowTicketVo();
                totalShowTicketVo.setTitle("合计");
                totalShowTicketVo.setAgentSaleNum(BigDecimal.ZERO);
                totalShowTicketVo.setTotalPrice(BigDecimal.ZERO);
                //根据票提IDs查询票信息
                List<TicketAndStatusDao> ticketAndStatusDaoList = kylinTicketsMapper.selectTicketsByIds(ticketsIdList);
                if (ticketAndStatusDaoList != null && ticketAndStatusDaoList.size() > 0) {
                    for (TicketAndStatusDao ticketAndStatusDao : ticketAndStatusDaoList) {
                        SmileAgent smileAgent = map.get(ticketAndStatusDao.getTicketsId());

                        ShowAgentVo showAgentVo = getShowAgentVo(performancesId, ticketAndStatusDao, smileAgent);

                        ShowTicketVo showTicketVo = new ShowTicketVo();
                        showTicketVo.setTitle(ticketAndStatusDao.getTitle());
                        //单价
                        showTicketVo.setPrice(ticketAndStatusDao.getPrice());
                        showTicketVo.setType(ticketAndStatusDao.getType());
                        showTicketVo.setUseEnd(ticketAndStatusDao.getUseEnd());
                        showTicketVo.setUseStart(ticketAndStatusDao.getUseStart());
                        showTicketVo.setTotalGeneral(ticketAndStatusDao.getTotalGeneral());

                        //根据演出id和票提id查询出一共卖出票的数量
                        Map numAndPrice = kylinOrderTicketsMapper.selectNumAndPrice(performancesId, ticketAndStatusDao.getTicketsId());
                        //销售总数
                        showTicketVo.setAgentSaleNum(numAndPrice != null ? (BigDecimal) numAndPrice.get("agentSaleNum") : BigDecimal.valueOf(0));
                        //销售金额
                        showTicketVo.setTotalPrice(numAndPrice != null ? (BigDecimal) numAndPrice.get("totalPrice") : BigDecimal.valueOf(0));

                        showAgentVoList.add(showAgentVo);
                        showTicketVoList.add(showTicketVo);

                        totalShowTicketVo.setTotalPrice(totalShowTicketVo.getTotalPrice().add(showTicketVo.getTotalPrice()));
                        totalShowTicketVo.setAgentSaleNum(totalShowTicketVo.getAgentSaleNum().add(showTicketVo.getAgentSaleNum()));
                    }
                    showTicketVoList.add(totalShowTicketVo);
                } else {
                    return AjaxResult.warn("查询票提信息失败");
                }
            }

            getShowVo(showVoById, kylinPerformanceVo, showAgentVoList, showTicketVoList);

            return AjaxResult.success(showVoById);
        }
        return AjaxResult.warn("请重试");
    }

    private void getShowVo(ShowVoById showVoById, KylinPerformanceVo kylinPerformanceVo, List<ShowAgentVo> showAgentVoList, List<ShowTicketVo> showTicketVoList) {
        showVoById.setPerformancesId(kylinPerformanceVo.getPerformancesId());
        showVoById.setImgPoster(kylinPerformanceVo.getImgPoster());
        showVoById.setTitle(kylinPerformanceVo.getTitle());
        showVoById.setTimeStart(kylinPerformanceVo.getTimeStart());
        showVoById.setTimeEnd(kylinPerformanceVo.getTimeEnd());
        showVoById.setCityId(kylinPerformanceVo.getCityId());
        showVoById.setCityName(kylinPerformanceVo.getCityName());
        showVoById.setFieldId(kylinPerformanceVo.getFieldId());
        showVoById.setFieldName(kylinPerformanceVo.getFieldName());
        showVoById.setShowAgentVoList(showAgentVoList);
        showVoById.setShowTicketVoList(showTicketVoList);
        showVoById.setDetails(kylinPerformanceVo.getDetails());
    }

    @Override
    public SaleDataVo saleData(String performancesId) {
        SaleDataVo saleDataVo = new SaleDataVo();
        //演出id
        saleDataVo.setPerformancesId(performancesId);
        //设置演出状态
        saleDataVo.setPriceStatus(smileRedisUtils.getShowPriceId(performancesId));
        List<SmileAgent> smileAgents = getSmileAgentsByProId(performancesId);
        if (smileAgents == null) {
            return null;
        }
        //演出名称
        KylinPerformanceVo kylinPerformanceVo = mongoTemplate.findOne(Query.query(Criteria.where("performancesId").is(performancesId)), KylinPerformanceVo.class, KylinPerformanceVo.class.getSimpleName());
        if (kylinPerformanceVo == null) {
            return null;
        }
        saleDataVo.setTitle(kylinPerformanceVo.getTitle());
        //map 票提id，票提信息
        Map<String, SmileAgent> map = getSmileAgentMap(smileAgents);

        List<String> ticketsIdList = smileAgents.stream().map(SmileAgent::getTicketId).collect(Collectors.toList());

        List<ShowAgentVo> showAgentVoList = new ArrayList<>();
        //根据票提IDs查询票信息
        List<TicketAndStatusDao> ticketAndStatusDaoList = kylinTicketsMapper.selectTicketsByIds(ticketsIdList);
        for (TicketAndStatusDao ticketAndStatusDao : ticketAndStatusDaoList) {
            SmileAgent smileAgent = map.get(ticketAndStatusDao.getTicketsId());
            ShowAgentVo showAgentVo = getShowAgentVo(performancesId, ticketAndStatusDao, smileAgent);
            showAgentVoList.add(showAgentVo);
        }

        //根据演出id查询出所有代理人的uid
        List<SmileUser> smileUsers = smileUserMapper.getAllUidByPerId(performancesId);
        List<UserData> userDataList = new ArrayList<>(smileUsers.size());
        for (SmileUser smileUser : smileUsers) {
            UserData userData = getUserData(performancesId, smileUser, map, ticketAndStatusDaoList);
            userDataList.add(userData);
        }
        saleDataVo.setUserDataList(userDataList);
        saleDataVo.setShowAgentVoList(showAgentVoList);
        return saleDataVo;
    }

    @Override
    public AjaxResult allPrice(SmilePriceParam smilePriceParam) {
        Integer showPriceId = smileRedisUtils.getShowPriceId(smilePriceParam.getPerformancesId());
        //查询演出状态
        AjaxResult showStatue = showStatue(smilePriceParam);
        if (showStatue != null) {
            return showStatue;
        }
        //判断打款标识
        if (smilePriceParam.getStatus().equals(showPriceId)) {
            return AjaxResult.warn("不可重复提交");
        }
        if (smilePriceParam.getStatus().equals(0)) {
            //打款
            smileRedisUtils.setShowPriceId(smilePriceParam.getPerformancesId());
        } else {
            //未打款
            smileRedisUtils.delShowPriceId(smilePriceParam.getPerformancesId());
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult updateRedis() {
        try {
            String perIds = (String) smileRedisUtils.get(SmileRedisConst.SMILE_SHOW);
            if(StringUtils.isNotBlank(perIds)){
                List<String> list = new ArrayList<>(Arrays.asList(perIds.split(",")));
                smileRedisUtils.setShowIds(list);
            }
        } catch (Exception e) {
            log.error("updateRedis()");
        }
        ArrayList<String> showIds = (ArrayList<String>) smileRedisUtils.getShowIds().stream().distinct().collect(Collectors.toList());
        smileRedisUtils.setShowIds(showIds);
        return AjaxResult.success(showIds);
    }

    private UserData getUserData(String performancesId, SmileUser smileUser, Map<String, SmileAgent> map, List<TicketAndStatusDao> smileAgentList) {
        UserData userData = new UserData();
        //个人用户的演出数据详情
        //便利票种id 查询用户的销售数据信息
        List<UserDataAgentVo> userDataAgentVos = new ArrayList<>();
        for (TicketAndStatusDao smileAgent : smileAgentList) {
            UserDataAgentVo userDataAgentVo = new UserDataAgentVo();
            Map userMap = smileAgentMapper.getUserDataByPerIdAndTicketsId(performancesId, smileUser.getUid(), smileAgent.getTicketsId());
            if (userMap != null) {
                userDataAgentVo.setTicketsId((String) userMap.get("tid"));
                userDataAgentVo.setTicketName((String) userMap.get("title"));
                userDataAgentVo.setNumber((BigDecimal) userMap.get("num"));
                userDataAgentVo.setPrice((BigDecimal) userMap.get("price"));
                userDataAgentVo.setAgent((BigDecimal) userMap.get("use"));
                userDataAgentVo.setCommission(((BigDecimal) userMap.get("totalPrice")).setScale(2, RoundingMode.HALF_UP));
            } else {
                userDataAgentVo.setTicketsId(smileAgent.getTicketsId());
                userDataAgentVo.setTicketName(smileAgent.getTitle());
                userDataAgentVo.setNumber(new BigDecimal(0));
                userDataAgentVo.setPrice(new BigDecimal(0));
                userDataAgentVo.setAgent(smileUser.getType() == 1 ? map.get(smileAgent.getTicketsId()).getTotalCarry() : map.get(smileAgent.getTicketsId()).getOrdCarry());
                userDataAgentVo.setCommission(new BigDecimal("0.00"));
                log.debug("saleData：演出id:{},用户id:{},票提id:{}", performancesId, smileUser.getUid(), smileAgent.getTicketsId());
            }
            //判断该用户是否是总代理
            if (smileUser.getType() == 1) {
                //是总代  //在原有的数据上新增加该用户下所有普代的提成
                Map orgMap = smileAgentMapper.getUserOrgByPerIdAndUidAndAgentMaster(performancesId, smileUser.getUid(), smileAgent.getTicketsId());
                if (orgMap != null) {
                    userDataAgentVo.setCommission((userDataAgentVo.getCommission().add((BigDecimal) orgMap.get("totalPrice"))).setScale(2, RoundingMode.HALF_UP));
                } else {
                    log.debug("saleData：演出id:{},用户id:{},票提id:{}", performancesId, smileUser.getUid(), smileAgent.getTicketsId());
                }
            }
//            if (userDataAgentVo.getCommission().compareTo(new BigDecimal(0)) != 0) {
            userDataAgentVos.add(userDataAgentVo);
//            }
        }
        userData.setUid(smileUser.getUid());
        userData.setUsername(smileUser.getName());
        userData.setCityName(smileUser.getCity());
        userData.setType(smileUser.getType());
        userData.setDataAgentVos(userDataAgentVos);
        //设置打款状态
        userData.setPriceStatus(smileRedisUtils.getShowPriceUid(performancesId, smileUser.getUid()));
        return userData;
    }

    private Map<String, SmileAgent> getSmileAgentMap(List<SmileAgent> smileAgents) {
        Map<String, SmileAgent> map = new HashMap<>(smileAgents.size());
        smileAgents.forEach(smileAgent -> map.put(smileAgent.getTicketId(), smileAgent));
        return map;
    }

    private List<SmileAgent> getSmileAgentsByProId(String performancesId) {
        LambdaQueryWrapper<SmileAgent> queryWrapper = Wrappers.lambdaQuery(SmileAgent.class);
        queryWrapper.eq(SmileAgent::getPerformanceId, performancesId);
        queryWrapper.eq(SmileAgent::getDelTag, 0);
        return smileAgentMapper.selectList(queryWrapper);
    }

    private ShowAgentVo getShowAgentVo(String performancesId, TicketAndStatusDao ticketAndStatusDao, SmileAgent smileAgent) {
        ShowAgentVo showAgentVo = new ShowAgentVo();
        showAgentVo.setId(ticketAndStatusDao.getMid());
        showAgentVo.setPerformanceId(performancesId);
        showAgentVo.setTicketId(ticketAndStatusDao.getTicketsId());
        showAgentVo.setTitle(ticketAndStatusDao.getTitle());
        //总代票提
        showAgentVo.setTotalCarry(smileAgent.getTotalCarry());
        //普代票提
        showAgentVo.setOrdCarry(smileAgent.getOrdCarry());
        return showAgentVo;
    }


}
