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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.ym.mec.biz.dal.dao.StudentPaymentRouteOrderDao;
import com.ym.mec.biz.dal.dao.SysConfigDao;
import com.ym.mec.biz.dal.dao.TeacherDao;
import com.ym.mec.biz.dal.dao.TenantEntryActivitiesDao;
import com.ym.mec.biz.dal.dao.TenantPaymentOrderDao;
import com.ym.mec.biz.dal.dto.PageInfoOrder;
import com.ym.mec.biz.dal.entity.StudentPaymentRouteOrder;
import com.ym.mec.biz.dal.entity.SysTenantAccountDetail.TransType;
import com.ym.mec.biz.dal.entity.Teacher;
import com.ym.mec.biz.dal.entity.TenantEntryActivities;
import com.ym.mec.biz.dal.entity.TenantEntryActivities.SuitableUser;
import com.ym.mec.biz.dal.entity.TenantPaymentOrder;
import com.ym.mec.biz.dal.entity.TenantPaymentOrder.TenantPaymentType;
import com.ym.mec.biz.dal.enums.DealStatusEnum;
import com.ym.mec.biz.dal.enums.PaymentChannelEnum;
import com.ym.mec.biz.dal.page.TenantPaymentOrderQueryInfo;
import com.ym.mec.biz.service.HfMerchantConfigService;
import com.ym.mec.biz.service.PayService;
import com.ym.mec.biz.service.SysTenantAccountService;
import com.ym.mec.biz.service.TenantPaymentOrderService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
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.thirdparty.adapay.ConfigInit;
import com.ym.mec.thirdparty.adapay.Payment;
import com.ym.mec.thirdparty.adapay.entity.HfMerchantConfig;
import com.ym.mec.thirdparty.yqpay.Msg;
import com.ym.mec.thirdparty.yqpay.RsqMsg;
import com.ym.mec.thirdparty.yqpay.YqPayFeignService;
import com.ym.mec.thirdparty.yqpay.YqPayUtil;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;

@Service
public class TenantPaymentOrderServiceImpl extends BaseServiceImpl<Long, TenantPaymentOrder> implements TenantPaymentOrderService {

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

    @Autowired
    private TenantPaymentOrderDao tenantPaymentOrderDao;

    @Autowired
    private TenantEntryActivitiesDao tenantEntryActivitiesDao;

    @Autowired
    private IdGeneratorService idGeneratorService;

    @Autowired
    private PayService payService;

    @Autowired
    private SysConfigDao sysConfigDao;

    @Autowired
    private TeacherDao teacherDao;

    @Autowired
    private SysTenantAccountService sysTenantAccountService;

    @Autowired
    private YqPayFeignService yqPayFeignService;
    @Autowired
    private StudentPaymentRouteOrderDao studentPaymentRouteOrderDao;
    
    @Autowired
    private HfMerchantConfigService hfMerchantConfigService;

    @Override
    public BaseDAO<Long, TenantPaymentOrder> getDAO() {
        return tenantPaymentOrderDao;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public HttpResponseResult createOrder(Integer userId, Integer activitiesId, boolean isContinuePay) {

        Teacher teacher = teacherDao.get(userId);
        if (teacher == null) {
            throw new BizException("用户信息不存在");
        }

        Integer organId = teacher.getTeacherOrganId();

        TenantEntryActivities tenantEntryActivities = tenantEntryActivitiesDao.get(activitiesId);
        if (tenantEntryActivities == null) {
            throw new BizException("活动不存在");
        }

        Date date = new Date();
        // 判断活动是否有效
        if (tenantEntryActivities.getDelFlag() == true) {
            throw new BizException("活动已下架");
        }
        if (date.before(tenantEntryActivities.getStartDate())) {
            throw new BizException("活动未开始");
        }
        if (date.after(tenantEntryActivities.getEndDate())) {
            throw new BizException("活动已结束");
        }

        // 查询用户订单
        List<TenantPaymentOrder> orderList = tenantPaymentOrderDao.queryByUserIdAndActivitiesId(userId, activitiesId);
        if (orderList != null && orderList.size() > 0) {
            for (TenantPaymentOrder po : orderList) {
                // 是否满足条件
                if (tenantEntryActivities.getSuitableUser() == SuitableUser.NEW) {
                    if (po.getStatus() == DealStatusEnum.SUCCESS) {
                        throw new BizException("首充优惠活动每个用户限参与一次。");
                    }

                    if (po.getStatus() == DealStatusEnum.ING) {
                        int i = 35 - DateUtil.minutesBetween(po.getCreateTime(), date);
                        if (i <= 0) {
                            throw new BizException("您有支付中的订单出现异常，请联系客服");
                        }
                        // throw new BizException("您参加的首充活动正在处理中，预计于{}分钟后处理完毕，请稍后。", i);
                        if (isContinuePay == false) {
                            HttpResponseResult result = new HttpResponseResult(true, HttpStatus.CONTINUE, "您存在支付中的订单，是否重新付款？", null);
                            return result;
                        } else {
                            // 关闭原订单
                            po.setStatus(DealStatusEnum.CLOSE);
                            po.setMemo("用户主动关闭");
                            po.setUpdateTime(date);
                            tenantPaymentOrderDao.update(po);
                        }
                    }
                }
            }
        }

        TenantPaymentOrder tenantPaymentOrder = new TenantPaymentOrder();
        tenantPaymentOrder.setUserId(userId);
        tenantPaymentOrder.setTransMinutes(tenantEntryActivities.getPurchaseMinutes());
        tenantPaymentOrder.setGiveMinutes(tenantEntryActivities.getGiveMinutes());
        tenantPaymentOrder.setOrderNo(idGeneratorService.generatorId("payment") + "");
        tenantPaymentOrder.setType(TenantPaymentType.RECHARGE);
        tenantPaymentOrder.setExpectAmount(tenantEntryActivities.getDiscountPrice());
        tenantPaymentOrder.setStatus(DealStatusEnum.ING);
        tenantPaymentOrder.setCreateTime(date);
        tenantPaymentOrder.setUpdateTime(date);
        tenantPaymentOrder.setVersion(0);
        tenantPaymentOrder.setOrganId(organId);
        tenantPaymentOrder.setActivitiesId(activitiesId);
        tenantPaymentOrderDao.insert(tenantPaymentOrder);

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

        // 分类费用 course，instrument，accessories，other
        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", BigDecimal.ZERO);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", tenantPaymentOrder.getExpectAmount());

        try {

            Map<String, Object> payMap = payService.getPayMap(
                    tenantPaymentOrder.getExpectAmount(),
                    BigDecimal.ZERO,
                    tenantPaymentOrder.getOrderNo(),
                    baseApiUrl + "/api-teacher/teacherOrder/callback",
                    baseApiUrl + "/api-teacher/teacherOrder/paymentResult?orderNo=" + tenantPaymentOrder.getOrderNo(),
                    "商户入驻",
                    "商户充值",
                    organId,
                    "tenantPayment"
            );

            tenantPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
            tenantPaymentOrder.setPaymentChannel(PaymentChannelEnum.valueOf(payMap.get("type").toString()));
            tenantPaymentOrder.setUpdateTime(date);
            tenantPaymentOrderDao.update(tenantPaymentOrder);

            HttpResponseResult result = new HttpResponseResult(true, HttpStatus.OK, payMap, null);
            return result;
        } catch (Exception e) {
            throw new BizException("调用支付接口出错", e);
        }
    }

    @Override
    public TenantPaymentOrder queryByOrderNo(String orderNo) {
        return tenantPaymentOrderDao.findOrderByOrderNo(orderNo);
    }

    @Override
    public Object queryTenanPaymentPage(TenantPaymentOrderQueryInfo queryInfo) {
        PageInfoOrder<TenantPaymentOrder> pageInfo = new PageInfoOrder<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);
        List<TenantPaymentOrder> dataList = new ArrayList<>();
        int count = this.findCount(params);
        if (count > 0) {
            TenantPaymentOrder orderMoneyAmount = tenantPaymentOrderDao.getOrderMoneyAmount(params);
            if (orderMoneyAmount != null) {
                pageInfo.setTotalExpectAmount(orderMoneyAmount.getExpectAmount() != null ? orderMoneyAmount.getExpectAmount() : BigDecimal.ZERO);
                pageInfo.setTotalActualAmount(orderMoneyAmount.getActualAmount() != null ? orderMoneyAmount.getActualAmount() : BigDecimal.ZERO);
            }
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = tenantPaymentOrderDao.queryPage(params);
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }
}
