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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.entity.Organization;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ym.mec.biz.dal.dto.PageInfoDegree;
import com.ym.mec.biz.dal.entity.DegreeRegistration;
import com.ym.mec.biz.dal.entity.SporadicChargeInfo;
import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
import com.ym.mec.biz.dal.enums.DealStatusEnum;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.OrderTypeEnum;
import com.ym.mec.biz.dal.page.DegreeQueryInfo;
import com.ym.mec.biz.service.DegreeRegistrationService;
import com.ym.mec.biz.service.PayService;
import com.ym.mec.biz.service.StudentPaymentOrderService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.util.collection.MapUtil;

@Service
public class DegreeRegistrationServiceImpl extends BaseServiceImpl<Integer, DegreeRegistration> implements DegreeRegistrationService {

    @Autowired
    private DegreeRegistrationDao degreeRegistrationDao;

    @Autowired
    private SporadicChargeInfoDao sporadicChargeInfoDao;

    @Autowired
    private IdGeneratorService idGeneratorService;

    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;

    @Autowired
    private SysConfigDao sysConfigDao;

    @Autowired
    private PayService payService;

    @Autowired
    private OrganizationDao organizationDao;

    @Override
    public BaseDAO<Integer, DegreeRegistration> getDAO() {
        return degreeRegistrationDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map pay(DegreeRegistration degreeRegistration) throws Exception {
        Date nowDate = new Date();
        //获取收费项价格
        SporadicChargeInfo chargeInfo = sporadicChargeInfoDao.get(degreeRegistration.getSporadicId());
        if (chargeInfo == null || chargeInfo.getDelFlag().equals(1) || chargeInfo.getOpenFlag().equals(1)) {
            throw new BizException("你选的考试级别不存在");
        }

        if (!chargeInfo.getTitle().equals("一级") && !chargeInfo.getTitle().equals("二级") && StringUtils.equals("免考", degreeRegistration.getTheoryLevel())
                && StringUtils.isBlank(degreeRegistration.getTheoryCert())) {
            throw new BizException("报考级别为“" + chargeInfo.getTitle() + "”且乐理级别是“免考”时,必须上传证书");
        }

        List<Organization> organs = organizationDao.findAllOrgans();
        Integer organId = chargeInfo.getOrganId();
        for (Organization organ : organs) {
            if (degreeRegistration.getCity().contains(organ.getName())) {
                organId = organ.getId();
                break;
            }
        }

        String orderNo = idGeneratorService.generatorId("payment") + "";

        degreeRegistration.setLevel(chargeInfo.getTitle());
        degreeRegistration.setOrderNo(orderNo);
        degreeRegistration.setOrganId(organId);
        BigDecimal theoryMoney = BigDecimal.ZERO;
        switch (degreeRegistration.getTheoryLevel()) {
            case "一级":
                theoryMoney = new BigDecimal(200);
                break;
            case "二级":
                theoryMoney = new BigDecimal(240);
                break;
            case "三级":
                theoryMoney = new BigDecimal(280);
                break;
            case "四级":
                theoryMoney = new BigDecimal(320);
                break;
            case "免考":
                break;
            default:
                throw new BizException("您选择的乐理级别不存在，请核对");
        }
        degreeRegistration.setTheoryMoney(theoryMoney);
        DegreeRegistration degree = degreeRegistrationDao.findByMobileAndSporadicId(degreeRegistration.getMobile(), degreeRegistration.getSporadicId());
        if (degree == null) {
            degreeRegistration.setMoney(chargeInfo.getAmount());
            degreeRegistration.setStatus(1);
            degreeRegistration.setCreateTime(nowDate);
            degreeRegistration.setUpdateTime(nowDate);
            degreeRegistrationDao.insert(degreeRegistration);
        } else if (degree.getStatus().equals(2)) {
            throw new BizException("您本次已报名，请勿重复报名");
        } else {
            degreeRegistration.setId(degree.getId());
            degreeRegistration.setStatus(1);
            degreeRegistration.setCreateTime(nowDate);
            degreeRegistration.setUpdateTime(nowDate);
            degreeRegistrationDao.update(degreeRegistration);
        }
        degreeRegistrationDao.getLock(degreeRegistration.getId());


        BigDecimal amount = chargeInfo.getAmount();
        amount = amount.add(theoryMoney);

        OrderTypeEnum type = OrderTypeEnum.SPORADIC;

        Integer userId = degreeRegistration.getId();
        String channelType = "";
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setGroupType(GroupType.SPORADIC);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(type);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(degreeRegistration.getSporadicId().toString());
        studentPaymentOrder.setOrganId(organId);
        studentPaymentOrder.setRoutingOrganId(organId);
        if (theoryMoney.compareTo(BigDecimal.ZERO) > 0) {
            studentPaymentOrder.setMemo("乐理" + degreeRegistration.getTheoryLevel() + ",费用：" + theoryMoney);
        }
        studentPaymentOrderService.insert(studentPaymentOrder);
        studentPaymentOrder.setVersion(0);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        String receiver = "kjRegister";
        Map payMap = payService.getPayMap(
                amount,
                BigDecimal.ZERO,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                chargeInfo.getDetail(),
                chargeInfo.getDetail(),
                organId,
                receiver
        );

        studentPaymentOrder.setOrganId(organId);
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(nowDate);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    public Boolean updateStatus(Integer id, Integer status, String orderNo) {
        DegreeRegistration degree = degreeRegistrationDao.getLock(id);
        if (degree == null || degree.getStatus().equals(2)) {
            return true;
        }
        StudentPaymentOrder order = studentPaymentOrderService.findOrderByOrderNo(orderNo);
        degree.setOrderNo(orderNo);
        degree.setTransNo(order.getTransNo());
        degree.setStatus(status);
        degree.setUpdateTime(new Date());
        if (degreeRegistrationDao.update(degree) <= 0) {
            throw new BizException("更新支付状态失败");
        }
        return true;
    }

    @Override
    public PageInfoDegree<DegreeRegistration> getPageList(DegreeQueryInfo queryInfo) {
        PageInfoDegree<DegreeRegistration> pageInfo = new PageInfoDegree<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<DegreeRegistration> dataList = new ArrayList<>();
        int count = this.findCount(params);

        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = degreeRegistrationDao.queryPage(params);
            DegreeRegistration degree = degreeRegistrationDao.getTotalAmount(params);
            BigDecimal subjectLevelAmount = degree.getMoney() == null ? BigDecimal.ZERO : degree.getMoney();
            BigDecimal theoryLevelAmount = degree.getTheoryMoney() == null ? BigDecimal.ZERO : degree.getTheoryMoney();
            BigDecimal totalAmount = subjectLevelAmount.add(theoryLevelAmount);

            pageInfo.setSubjectLevelAmount(subjectLevelAmount);
            pageInfo.setTheoryLevelAmount(theoryLevelAmount);
            pageInfo.setTotalAmount(totalAmount);
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }
}
