package com.ym.mec.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ym.mec.biz.dal.dao.CloudTeacherOrderDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDao;
import com.ym.mec.biz.dal.dto.CloudTeacherOrderDto;
import com.ym.mec.biz.dal.dto.Mapper;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.dal.enums.PaymentChannelEnum;
import com.ym.mec.biz.dal.enums.TenantOrderRecordEnum;
import com.ym.mec.biz.dal.page.CloudTeacherOrderQueryInfo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.WrapperUtil;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.enums.PeriodEnum.*;

@Service
public class CloudTeacherOrderServiceImpl extends BaseServiceImpl<Long, CloudTeacherOrder> implements CloudTeacherOrderService {

    private static final Logger log = LoggerFactory.getLogger(CloudTeacherOrderServiceImpl.class);
    @Autowired
    private CloudTeacherOrderDao cloudTeacherOrderDao;
    @Autowired
    private StudentService studentService;
    @Autowired
    private MusicGroupPaymentCalenderMemberService musicGroupPaymentCalenderMemberService;
    @Autowired
    private TenantConfigService tenantConfigService;
    @Autowired
    private PayService payService;
    @Autowired
    private IdGeneratorService idGenerator;
    @Autowired
    private TenantOrderRecordService tenantOrderRecordService;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;

    @Override
    public BaseDAO<Long, CloudTeacherOrder> getDAO() {
        return cloudTeacherOrderDao;
    }
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private TenantInfoService tenantInfoService;


    @Override
    public PageInfo<CloudTeacherStudent> queryRecord(CloudTeacherOrderQueryInfo queryInfo) {
        PageInfo<CloudTeacherStudent> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        List<CloudTeacherStudent> dataList = null;
        int count = cloudTeacherOrderDao.findRecordCount(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = cloudTeacherOrderDao.queryRecord(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);

        return pageInfo;
    }

    @Override
    public PageInfo<CloudTeacherStudent> queryInactive(CloudTeacherOrderQueryInfo queryInfo) throws Exception {
        PageInfo<CloudTeacherStudent> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        List<CloudTeacherStudent> dataList = null;
        int count = cloudTeacherOrderDao.findInactiveCount(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = cloudTeacherOrderDao.queryInactive(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);

        if (count == 0) {
            return pageInfo;
        }
        assert dataList != null;
        for (CloudTeacherStudent cst : dataList) {
            TenantConfig tenantConfig = tenantConfigService.getOne(new QueryWrapper<TenantConfig>().eq("tenant_id_", cst.getTenantId()));
            if (tenantConfig == null) {
                throw new Exception("未找到组织Id " + cst.getTenantId().toString() + "在 TenantConfig 表");
            }
            JSONObject cfg = JSON.parseObject(tenantConfig.getConfig());
            JSONObject memberConfig = (JSONObject) cfg.get("member_config");
            Double divide;
            switch (cst.getType()) {
                case DAY:
                    divide = memberConfig.getDouble("day_divide");
                    break;
                case MONTH:
                    divide = memberConfig.getDouble("month_divide");
                    break;
                case QUARTERLY:
                    divide = memberConfig.getDouble("quarter_divide");
                    break;
                case YEAR_HALF:
                    divide = memberConfig.getDouble("half_year_divide");
                    break;
                case YEAR:
                    divide = memberConfig.getDouble("year_divide");
                    break;
                default:
                    divide = null;
            }
            if (divide == null) {
                cst.setAmount(null);
            } else {
                cst.setAmount(new BigDecimal(divide * cst.getTime()));
            }
        }
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> pay(List<CloudTeacherStudent> cloudTeacherStudents) throws Exception {

        if (cloudTeacherStudents.size() == 0) {
            throw new Exception("请选择选择一条记录");
        }
        List<Integer> ids = cloudTeacherStudents.stream().map(CloudTeacherStudent::getCloudTeacherOrderId).collect(
                Collectors.toList());
        if (cloudTeacherOrderDao.checkOrdered(StringUtil.join(ids, ",")) != 0) {
            throw new Exception("存在已经支付完成的学生，请重新选择");
        }
        Integer tenantId = null;
        BigDecimal sumAmount = new BigDecimal(0);
        for (CloudTeacherStudent cts : cloudTeacherStudents) {
            if (cts.getAmount() == null) {
                throw new Exception("支付金额异常, 请按规定操作 ");
            }
            sumAmount = sumAmount.add(cts.getAmount());
            if (tenantId == null) {
                tenantId = cts.getTenantId();
            }
        }
        return this.payExec(sumAmount, tenantId, cloudTeacherStudents);
    }

    /**
     * 团练宝支付
     *
     * @param payAmount 金额
     * @param tenantId  分部
     * @return 支付结果
     */
    private Map<String, Object> payExec(BigDecimal payAmount, Integer tenantId, List<CloudTeacherStudent> cloudTeacherStudents) throws Exception {
        //生成订单编号
        String orderNo = idGenerator.generatorId("payment") + "";
        TenantOrderRecordEnum tenantEnum = TenantOrderRecordEnum.CLOUD_TEACHER;

        Map<String, Object> payMap = new HashMap<>();
        int orderState = 0;
        //消费大于0元则拉起支付
        if (payAmount.compareTo(BigDecimal.ZERO) > 0) {
            payMap = payService.getPayToPlatformMap(tenantId,
                    PaymentChannelEnum.ADAPAY,
                    payAmount,
                    BigDecimal.ZERO,
                    orderNo,
                    null,
                    null,
                    tenantEnum.getMsg(),
                    tenantEnum.getMsg()
            );
        } else { // 消费大于 0 元 已支付 直接激活
            orderState = 1;
        }
        payMap.put("amount", payAmount);
        payMap.put("orderNo", orderNo);
        TenantOrderRecord record = tenantInfoService.createOrderRecord(tenantId, payAmount, orderNo, tenantEnum, orderState, WrapperUtil.toStr(payMap, "routingMerNos"));
        for (CloudTeacherStudent cts : cloudTeacherStudents) {
            if (cloudTeacherOrderDao.updateOrderId(cts.getCloudTeacherOrderId(), cts.getAmount(), record.getId()) <= 0) {
                throw new Exception("更新订单失败");
            }
        }
        //0元直接成功
        if (orderState == 1) {
            tenantOrderRecordService.activeCloudTeacher(record);
        }
        log.info("tenant pay >>>>> " + JSON.toJSONString(payMap));
        return payMap;
    }

    @Override
    public int sendSms(TenantOrderRecord record) {
        List<Mapper> orderUsers = cloudTeacherOrderDao.findUserNameByOrderId(record.getId());
        Map<Integer, String> userPhones = new HashMap<>();
        for (Mapper mapper : orderUsers) {
            userPhones.put((Integer) mapper.getKey(), mapper.getValue().toString());
        }
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.CLOUD_TEACHER_ORDER_SUCCESS, userPhones, null, 0, null, null);
        return 0;
    }

    @Override
    public void batchInsert(CloudTeacherOrder cloudTeacherOrder, List<Integer> userIds,Boolean autoActivationFlag) {
        if(autoActivationFlag){
            Date date = new Date();
            for (Integer userId : userIds) {
                cloudTeacherOrder.setStudentId(userId);
                this.activationMember(date,cloudTeacherOrder);
            }
        }else {
            cloudTeacherOrderDao.batchInsert(cloudTeacherOrder,userIds);
        }
    }

    @Override
    public CloudTeacherOrder getInitCloudTeacherOrder(CloudCoachPaymentProgram cloudCoachPaymentProgram) {
        CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
        cloudTeacherOrder.setTime(cloudCoachPaymentProgram.getMemberNum().intValue());
        cloudTeacherOrder.setOrganId(cloudCoachPaymentProgram.getOrganId());
        cloudTeacherOrder.setType(cloudCoachPaymentProgram.getPeriod());
        cloudTeacherOrder.setLevel(cloudCoachPaymentProgram.getMemberRankSettingId());
        cloudTeacherOrder.setAmount(BigDecimal.ZERO);
        cloudTeacherOrder.setStatus(1);
        cloudTeacherOrder.setRemark(cloudCoachPaymentProgram.getRemark());
        return cloudTeacherOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(CloudTeacherOrder cloudTeacherOrder,Boolean autoActivationFlag) {
        if(autoActivationFlag){
            this.activationMember(new Date(),cloudTeacherOrder);
        }else {
            cloudTeacherOrderDao.insert(cloudTeacherOrder);
        }
    }

    @Override
    public CloudTeacherOrder queryByOrderId(Long orderId) {
        return cloudTeacherOrderDao.queryByOrderId(orderId);
    }

    public Boolean payCheck(String orderNo) {
        TenantOrderRecord record = tenantOrderRecordService.getOne(new QueryWrapper<TenantOrderRecord>().eq("order_no_", orderNo));
        return record.getOrderState() == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrderDetail2CloudTeacher(StudentPaymentOrder order, BigDecimal cloudTeacherFee) {
        CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
        cloudTeacherOrder.setTenantId(order.getTenantId());
        cloudTeacherOrder.setOrganId(order.getOrganId());
        cloudTeacherOrder.setOrderId(order.getId());
        MusicGroupPaymentCalenderMember calenderMember = musicGroupPaymentCalenderMemberService.findByCalenderId(order.getCalenderId());
        cloudTeacherOrder.setLevel(calenderMember.getMemberRankSettingId());
        cloudTeacherOrder.setTime(calenderMember.getNum().intValue());
        cloudTeacherOrder.setType(calenderMember.getPeriod());
        cloudTeacherOrder.setAmount(cloudTeacherFee);
        cloudTeacherOrder.setStudentId(order.getUserId());
        cloudTeacherOrder.setStatus(1);
        MusicGroupPaymentCalender calender = musicGroupPaymentCalenderDao.get(order.getCalenderId());
        if(calender.getCloudTeacherPaymentFlag()){
            cloudTeacherOrder.setOperatingAmount(BigDecimal.ZERO);
        }else {
            cloudTeacherOrder.setOperatingAmount(cloudTeacherFee);
        }
        //保存云教练订单
        this.save(cloudTeacherOrder,calenderMember.getAutoActivationFlag());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void activationMember(Date now,CloudTeacherOrder cloudTeacherOrder){
        Date startTime = DateUtil.trunc(now);
        Date endTime = this.calcCloudTeacherOrderTime(cloudTeacherOrder, startTime, now);
        cloudTeacherOrder.setStartTime(startTime);
        cloudTeacherOrder.setEndTime(DateUtil.addDays(endTime,1));
        cloudTeacherOrder.setStatus(2);
        if(Objects.isNull(cloudTeacherOrder.getId())){
            cloudTeacherOrderDao.insert(cloudTeacherOrder);
        }else {
            cloudTeacherOrderDao.update(cloudTeacherOrder);
        }
        studentService.updateMemberRank(cloudTeacherOrder.getStudentId(), cloudTeacherOrder.getType(), cloudTeacherOrder.getTime(), 1);
    }

    public Date calcCloudTeacherOrderTime(CloudTeacherOrder cloudTeacherOrder, Date startTime, Date endTime) {
        if (cloudTeacherOrder.getType() == DAY) { // 日
            endTime = DateUtil.addDays(startTime, cloudTeacherOrder.getTime());
        } else if (cloudTeacherOrder.getType() == MONTH) { // 月
            endTime = DateUtil.addMonths(startTime, cloudTeacherOrder.getTime());
        } else if (cloudTeacherOrder.getType() == QUARTERLY) { // 季
            endTime = DateUtil.addMonths(startTime, cloudTeacherOrder.getTime() * 3);
        } else if (cloudTeacherOrder.getType() == YEAR_HALF) { // 半年
            endTime = DateUtil.addMonths(startTime, cloudTeacherOrder.getTime() * 6);
        } else if (cloudTeacherOrder.getType() == YEAR) { // 年
            endTime = DateUtil.addYears(startTime, cloudTeacherOrder.getTime());
        }
        return endTime;
    }

    @Override
    public List<CloudTeacherOrder> getStudentCloudTeacherOrders(List<Integer> studentIds, String musicGroupId) {
        return cloudTeacherOrderDao.getStudentCloudTeacherOrders(studentIds, musicGroupId);
    }

    @Override
    public CloudTeacherOrderDto queryOrderInfoByOrderId(Long orderId) {
        return cloudTeacherOrderDao.queryOrderInfoByOrderId(orderId);
    }

    @Override
    public List<Map<Long, String>> queryNoStartByUserIds(Set<Integer> userIds, Boolean isMusicMember) {
        return cloudTeacherOrderDao.queryNoStartByUserIds(userIds, isMusicMember);
    }

    @Override
    public String queryActiveOrderPage(Integer userId, Integer activeRemark, String remark) {
        return cloudTeacherOrderDao.queryActiveOrderPage(userId, activeRemark, remark);
    }
}
