package com.ylx.massage.task;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ylx.common.constant.MassageConstants;
import com.ylx.common.core.domain.entity.SysDept;
import com.ylx.common.utils.DateUtils;
import com.ylx.common.utils.StringUtils;
import com.ylx.massage.domain.*;
import com.ylx.massage.enums.BillTypeEnum;
import com.ylx.massage.enums.JsStatusEnum;
import com.ylx.massage.enums.OrderStatusEnum;
import com.ylx.massage.mapper.TConsumptionLogMapper;
import com.ylx.massage.service.*;
import com.ylx.massage.utils.DateTimeUtils;
import com.ylx.massage.utils.LocationUtil;
import com.ylx.massage.utils.WeChatUtil;
import com.ylx.order.domain.TOrder;
import com.ylx.order.service.TOrderService;
import com.ylx.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

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


/**
 * @author jianlong
 * @date 2024-04-19 14:11
 */
@Slf4j
@Component("massageTask")
public class massageTask {

    @Resource
    private TOrderService orderService;

    @Resource
    private LocationUtil locationUtil;

    @Resource
    private TJsService jsService;

    @Resource
    private TSignService signService;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private TRechargeService rechargeService;
    @Resource
    private TJsDayService jsDayService;

    @Resource
    private TConsumptionLogService consumptionLogService;

    @Resource
    private TConsumptionLogMapper consumptionLogMapper;

    @Resource
    private TWxUserService userService;

    @Resource
    private WeChatUtil weChatUtil;

    @Value("${hCount}")
    private String hCount;

    @Value("${percent}")
    private String percent;

    /**
     * 取消超时未支付订单
     */
    public void cancelOrder() {

        Date nowDate = new Date();
        log.info("开始执行取消订单任务当前时间：{}", nowDate);

        Date date = DateTimeUtils.addMinute(nowDate, -5);
        log.info("开始执行取消订单任务当前时间减5分钟,{}", date);
        long total = 1L;
        while (total > 0L) {
            total = extracted(date);
        }
    }

    private Long extracted(Date nowDate) {
        log.info("extracted 开始执行取消订单任务时间,{}", nowDate);
        LambdaQueryWrapper<TOrder> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        objectLambdaQueryWrapper.eq(TOrder::getStatus, OrderStatusEnum.WAIT_PAY.getCode()).
                le(TOrder::getCreateTime, nowDate).
                orderByAsc(TOrder::getCreateTime);

        Page<TOrder> page = new Page<>();
        page.setSize(MassageConstants.TWO_HUNDRED);

        Page<TOrder> resPage = orderService.page(page, objectLambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(resPage.getRecords())) {
            resPage.getRecords().forEach(order -> {
                TOrder newOrder = new TOrder();
                //todo 订单锁
                newOrder.setId(order.getId());
                newOrder.setStatus(OrderStatusEnum.CANCEL.getCode());
                orderService.updateById(newOrder);
                log.info("取消超时未支付订单orderNo,{}", order.getOrderNo());
            });
        }
        return resPage.getTotal();
    }

    public void timeoutNotOrder() {

        Date nowDate = new Date();
        log.info("开始执行超时未接单任务,{}", nowDate);

        Date date = DateTimeUtils.addMinute(nowDate, -10);
        log.info("开始执行超时未接单任务当前时间减10分钟,{}", date);
        long total = 1L;
        while (total > 0L) {
            total = timeoutNotOrder(date);
        }
    }

    private Long timeoutNotOrder(Date nowDate) {
        LambdaQueryWrapper<TOrder> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        objectLambdaQueryWrapper.eq(TOrder::getStatus, OrderStatusEnum.WAIT_JD.getCode()).
                le(TOrder::getPaidTime, nowDate).
                orderByAsc(TOrder::getPaidTime);

        Page<TOrder> page = new Page<>();
        page.setSize(MassageConstants.TWO_HUNDRED);

        Page<TOrder> resPage = orderService.page(page, objectLambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(resPage.getRecords())) {
            resPage.getRecords().forEach(order -> {
                //调用拒绝接单
                order.setRejectedReason("超时未接单");
//                orderService.jujue(order);
            });
        }
        return resPage.getTotal();

    }


    public void isGetAmount() {
        Date nowDate = new Date();
        log.info("定时分配出账金额日期,{}", nowDate);

        Date date = DateTimeUtils.addDays(nowDate, -7);
        log.info("定时分配出账金额日期,{}", date);
        isGetAmount(date);
    }

    private void isGetAmount(Date date) {

        //查询所有部门
        List<SysDept> sysDepts = deptService.selectDeptList(new SysDept());
        //遍历部门技师
        sysDepts.forEach(sysDept -> {
            LambdaQueryWrapper<TJs> jsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            jsLambdaQueryWrapper.eq(TJs::getnTong, JsStatusEnum.JS_PASS.getCode()).eq(TJs::getDeptId, sysDept.getDeptId());
            List<TJs> jsList = jsService.list(jsLambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(jsList)) {
                jsList.forEach(js -> {
                    //根据技师openId 查询未领取金额
                    LambdaQueryWrapper<TConsumptionLog> logLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    logLambdaQueryWrapper.eq(TConsumptionLog::getIsGet, MassageConstants.INTEGER_ZERO).
                            eq(TConsumptionLog::getOpenId, js.getcOpenId()).
                            in(TConsumptionLog::getBillType, Arrays.asList(BillTypeEnum.INCOME.getCode(), BillTypeEnum.DISTRIBUTION.getCode())).
                            le(TConsumptionLog::getCreateTime, date).
                            orderByAsc(TConsumptionLog::getCreateTime);
                    List<TConsumptionLog> consumptionLogList = consumptionLogService.list(logLambdaQueryWrapper);

                    if (CollectionUtil.isNotEmpty(consumptionLogList)) {
                        //处理可提现金额
                        //1.修改余额记录状态
                        consumptionLogList.forEach(consumptionLog -> {
                            //修改状态未已到提现账户
                            consumptionLog.setIsGet(MassageConstants.INTEGER_ONE);
                        });
                        int i = consumptionLogMapper.insertOrUpdateBatch(consumptionLogList);
                        //2.修改技师提现账户
                        BigDecimal getAmount = consumptionLogList.stream().map(TConsumptionLog::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        TWxUser user = userService.getByOpenId(js.getcOpenId());
                        user.setGetAmount(user.getGetAmount().add(getAmount));
                        userService.updateById(user);
                    }
                });
            }
        });
    }


    public void cancelNewJs() {

        Date nowDate = new Date();
        log.info("开始执行取消新技师标识任务当前时间,{}", nowDate);

        long flag = 1L;
        while (flag > 0L) {
            LambdaQueryWrapper<TJs> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
            Date date = DateTimeUtils.addDays(nowDate, -7);

            log.info("开始执行取新技师当前时间减7天,{}", date);
            objectLambdaQueryWrapper.eq(TJs::getnB2, MassageConstants.INTEGER_ONE).
                    le(TJs::getcTime, date).
                    gt(TJs::getId, String.valueOf(flag)).
                    orderByAsc(TJs::getId);

            Page<TJs> page = new Page<>();
            page.setSize(MassageConstants.TWO_HUNDRED);

            Page<TJs> page1 = jsService.page(page, objectLambdaQueryWrapper);

            if (CollectionUtil.isNotEmpty(page1.getRecords())) {
                page1.getRecords().forEach(tjs -> {
                    TJs js = new TJs();
                    js.setId(tjs.getId());
                    js.setnB2(MassageConstants.INTEGER_ZERO);
                    jsService.updateById(js);
                    log.info("取消新技师标识,{}", js.getcOpenId() + js.getcName());
                });
                Optional<String> maxId = page1.getRecords().stream().max(Comparator.comparing(TJs::getId)).map(TJs::getId);
                flag = Long.parseLong(maxId.orElse("0"));
            } else {
                flag = 0L;
            }
        }
    }

    public void cancelHotJs() {

        Date nowDate = new Date();
        log.info("开始执行取消技师热度标识任务当前时间,{}", nowDate);

        Date date = DateTimeUtils.addDays(nowDate, -3);
        long flag = 1L;
        while (flag > 0L) {
            LambdaQueryWrapper<TJs> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
            objectLambdaQueryWrapper.eq(TJs::getnB3, MassageConstants.INTEGER_ONE).gt(TJs::getId, String.valueOf(flag)).orderByAsc(TJs::getId);

            Page<TJs> page = new Page<>();
            page.setSize(MassageConstants.TWO_HUNDRED);
            Page<TJs> page1 = jsService.page(page, objectLambdaQueryWrapper);

            if (CollectionUtil.isNotEmpty(page1.getRecords())) {
                page1.getRecords().forEach(tjs -> {
                    List<TOrder> list = orderService.list(new LambdaQueryWrapper<TOrder>().eq(TOrder::getMerchantId, tjs.getId()).ge(TOrder::getCreateTime, date));
                    if (CollectionUtil.isEmpty(list) || list.size() < 3) {
                        TJs js = new TJs();
                        js.setId(tjs.getId());
                        js.setnB3(MassageConstants.INTEGER_ZERO);
                        jsService.updateById(js);
                        log.info("取消热度技师标识,{}", js.getcOpenId() + js.getcName());
                    }
                });
                Optional<String> maxId = page1.getRecords().stream().max(Comparator.comparing(TJs::getId)).map(TJs::getId);
                flag = Long.parseLong(maxId.orElse("0"));
            } else {
                flag = 0L;
            }
        }
    }

    /**
     * 定时下岗
     * 12:01 查询前一天 是否有上岗记录
     * 如果有上岗记录 没有下岗记录
     * 插入一条(前一天)下岗记录(并计算在线时长) 和当天上岗记录
     *
     * @param date yyyy-MM-dd
     **/
    public void RegularLayoff(String date) {

        Date date2 = new Date();
        if (StringUtils.isNotBlank(date)) {
            date2 = DateTimeUtils.parseDate(date, DateTimeUtils.DATE_FORMAT);
        } else {
            date2 = DateTimeUtils.addDays(date2, -1);
        }
        Date startDate = DateTimeUtils.getStartDate(date2);
        Date endDate = DateTimeUtils.getEndDate(date2);
        long total = 1L;
        while (total > 0L) {
            Page<TSign> signPage = new Page<>();
            signPage.setSize(MassageConstants.TWO_HUNDRED);
            LambdaQueryWrapper<TSign> signLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //上岗

            signLambdaQueryWrapper.isNull(TSign::getLayoffTime).ge(TSign::getSingTime, startDate).le(TSign::getSingTime, endDate);
            Page<TSign> page = signService.page(signPage, signLambdaQueryWrapper);

            if (CollectionUtil.isNotEmpty(page.getRecords())) {
                page.getRecords().forEach(sign -> {
                    sign.setLayoffTime(endDate);
                    Long layoff = DateTimeUtils.dateToStamp(sign.getLayoffTime());
                    Long sing = DateTimeUtils.dateToStamp(sign.getSingTime());
                    Long time = layoff - sing;
                    time = time / 1000;
                    time = time / 60;
                    sign.setOnlineTime(time.intValue());
                    signService.updateById(sign);
                    //增加上岗记录
                    TSign tSign = new TSign();
                    tSign.setSingTime(endDate);
                    tSign.setName(sign.getName());
                    tSign.setJsId(sign.getJsId());
                    tSign.setDeptId(sign.getDeptId());
                    tSign.setDeptName(sign.getDeptName());
                    tSign.setOpenId(sign.getOpenId());
                    signService.save(tSign);
                });
            }
            total = page.getTotal();
        }
        //查询所有部门
        List<SysDept> sysDepts = deptService.selectDeptList(new SysDept());

        sysDepts.forEach(sysDept -> {
            //查询所有技师
            LambdaQueryWrapper<TJs> jsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            jsLambdaQueryWrapper.eq(TJs::getnTong, JsStatusEnum.JS_PASS.getCode()).eq(TJs::getDeptId, sysDept.getDeptId());
            List<TJs> jsList = jsService.list(jsLambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(jsList)) {
                jsList.forEach(js -> {
                    TJsDay tJsDay = new TJsDay();
                    tJsDay.setDeptName(js.getCity());
                    tJsDay.setDeptId(js.getDeptId());
                    tJsDay.setOpenId(js.getcOpenId());
                    tJsDay.setJsId(js.getId());
                    tJsDay.setName(js.getcName());
                    Integer onLine = signService.getOnLineTime(js.getId(), startDate, endDate);
                    tJsDay.setOnLine(onLine);
//                    Integer orderNum = orderService.getOrderNum(js.getId(), startDate, endDate);
//                    tJsDay.setOrderNum(orderNum);
//                    Integer addNum = orderService.getAddNum(js.getId(), startDate, endDate);
//                    tJsDay.setAddNum(addNum);
//                    Integer upgradeNum = orderService.getUpgradeNum(js.getId(), startDate, endDate);
//                    tJsDay.setUpgradeNum(upgradeNum);
//                    BigDecimal turnover = orderService.getTurnover(js.getId(), startDate, endDate);
//                    tJsDay.setTurnover(turnover);
                    BigDecimal recharge = rechargeService.getRecharge(js.getId(), startDate, endDate);
                    tJsDay.setRecharge(recharge);
                    tJsDay.setCountDate(DateTimeUtils.formatDate(startDate, DateTimeUtils.DATE_FORMAT));
                    jsDayService.save(tJsDay);
                });
            }
        });


    }

    public void sysJsWeiZhi() {
        log.info("开始执行同步技师位置时间,{}", DateUtils.getNowDate());
        long flag = 1L;
        while (flag > 0L) {
            LambdaQueryWrapper<TJs> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();

            objectLambdaQueryWrapper.gt(TJs::getId, String.valueOf(flag)).orderByAsc(TJs::getId);

            Page<TJs> page = new Page<>();
            page.setSize(MassageConstants.TWO_HUNDRED);
            Page<TJs> page1 = jsService.page(page, objectLambdaQueryWrapper);

            if (CollectionUtil.isNotEmpty(page1.getRecords())) {
                page1.getRecords().forEach(tjs -> {
                    if (StringUtils.isNotBlank(tjs.getcPhone()) && null != tjs.getLongitude() && null != tjs.getLatitude()) {
                        locationUtil.geoAdd(LocationUtil.GEO_KEY, tjs.getcPhone(),
                                Double.parseDouble(tjs.getLongitude().toString()),
                                Double.parseDouble(tjs.getLatitude().toString()));
                    }
                });
                Optional<String> maxId = page1.getRecords().stream().max(Comparator.comparing(TJs::getId)).map(TJs::getId);
                flag = Long.parseLong(maxId.orElse("0"));
            } else {
                flag = 0L;
            }
        }
        log.info("结束执行同步技师位置时间,{}", DateUtils.getNowDate());
    }

    public void sysJsWeiTicke() {
        log.info("开始执行同步技师二维码,{}", DateUtils.getNowDate());
        long flag = 1L;
        while (flag > 0L) {
            LambdaQueryWrapper<TJs> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();

            objectLambdaQueryWrapper.gt(TJs::getId, String.valueOf(flag)).orderByAsc(TJs::getId);

            Page<TJs> page = new Page<>();
            page.setSize(MassageConstants.TWO_HUNDRED);
            Page<TJs> page1 = jsService.page(page, objectLambdaQueryWrapper);

            if (CollectionUtil.isNotEmpty(page1.getRecords())) {
                page1.getRecords().forEach(tjs -> {
                    String token = weChatUtil.getToken();
                    //获取的二维码ticket
                    Map<?, ?> jsTicket = weChatUtil.getJsTicket(token, tjs.getId());
                    tjs.setTicket(jsTicket.get("ticket").toString());
                    jsService.updateById(tjs);
                });
                Optional<String> maxId = page1.getRecords().stream().max(Comparator.comparing(TJs::getId)).map(TJs::getId);
                flag = Long.parseLong(maxId.orElse("0"));
            } else {
                flag = 0L;
            }
        }
        log.info("结束执行同步技师二维码,{}", DateUtils.getNowDate());
    }

    /**
     * 1 <48小时 订单服务完成后 进行更新操作 订单状态已完成[nStatus=5]后  更新订单结算状态为待结算[wStatus=1]
     * 2 >48小时 订单结算状态更新为 已结算  自动分账  订单总金额划入用户余额
     */
    public void autoAccount() {
        log.info("开始执行同步自动分账,{}", DateUtils.getNowDate());
        //执行存储过程
//        //>48小时 订单状态 [待结算] 更新为 [已结算]  自动分账  订单总金额划入用户余额
//        orderService.callAutoAccount(Integer.parseInt(hCount), new BigDecimal(percent));

        log.info("执行同步自动分账结束,{}", DateUtils.getNowDate());

    }

}
