package com.gic.haoban.manage.service.service.out.impl.licence;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.commons.util.DateUtil;
import com.gic.commons.util.EntityUtil;
import com.gic.enterprise.api.dto.EnterpriseDTO;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.haoban.manage.api.dto.StaffActiveDataDTO;
import com.gic.haoban.manage.api.dto.WxEnterpriseDTO;
import com.gic.haoban.manage.api.dto.licence.LicenceOrderDTO;
import com.gic.haoban.manage.api.dto.licence.LicenceOrderPageDTO;
import com.gic.haoban.manage.api.dto.licence.LicenceOrderProgressDTO;
import com.gic.haoban.manage.api.dto.qdto.licence.LicenceOrderPageQDTO;
import com.gic.haoban.manage.api.dto.qdto.licence.LicenceOrderQDTO;
import com.gic.haoban.manage.api.service.WxEnterpriseApiService;
import com.gic.haoban.manage.api.service.licence.LicenceOrderApiService;
import com.gic.haoban.manage.service.config.Config;
import com.gic.haoban.manage.service.entity.fee.TabHaobanQywxFeeOrder;
import com.gic.haoban.manage.service.entity.licence.TabHaobanLicenceOrder;
import com.gic.haoban.manage.service.entity.licence.TabHaobanLicenceOrderProgress;
import com.gic.haoban.manage.service.service.StaffClerkRelationService;
import com.gic.haoban.manage.service.service.WxEnterpriseActiveDataService;
import com.gic.haoban.manage.service.service.WxEnterpriseService;
import com.gic.haoban.manage.service.service.fee.HaobanQywxFeeOrderService;
import com.gic.haoban.manage.service.service.licence.LicenceOrderProgressService;
import com.gic.haoban.manage.service.service.licence.LicenceOrderService;
import com.gic.haoban.manage.service.util.DingUtils;
import com.gic.redis.data.util.RedisUtil;
import com.gic.thirdparty.api.dto.RefundReqDataDTO;
import com.gic.thirdparty.api.dto.RefundResDataDTO;
import com.gic.thirdparty.api.service.Pay4WXService;
import com.gic.wechat.api.dto.qywx.fee.CreateOrderResponseDTO;
import com.gic.wechat.api.dto.qywx.fee.FeeOrderDeatilResponseDTO;
import com.gic.wechat.api.dto.qywx.fee.qdto.CreateOrderQDTO;
import com.gic.wechat.api.dto.qywx.response.QywxResponseDTO;
import com.gic.wechat.api.service.qywx.QywxOrderApiService;
import com.gic.wechat.api.service.qywx.QywxUserApiService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.redisson.client.RedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description:
 * @Author: wenhua
 * @Date: 2023/3/9 17:04
 */
@Service("licenceOrderApiServiceImpl")
public class LicenceOrderApiServiceImpl implements LicenceOrderApiService {

    private static final Logger logger = LogManager.getLogger(LicenceOrderApiServiceImpl.class);

    @Autowired
    private LicenceOrderService licenceOrderService;
    @Autowired
    private LicenceOrderProgressService licenceOrderProgressService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private WxEnterpriseApiService wxEnterpriseApiService;

    @Autowired
    private QywxOrderApiService qywxOrderApiService;
    @Autowired
    private Config config;
    @Autowired
    private WxEnterpriseService wxEnterpriseService;
    @Autowired
    private Pay4WXService pay4WXService;
    @Autowired
    private QywxUserApiService qywxUserApiService;
    @Autowired
    private StaffClerkRelationService staffClerkRelationService;
    @Autowired
    private WxEnterpriseActiveDataService wxEnterpriseActiveDataService;

    @Override
    public ServiceResponse<LicenceOrderDTO> getLicenceOrderDetail(Long orderId, Integer type) {
        TabHaobanLicenceOrder licenceOrderDetail = licenceOrderService.getLicenceOrderDetail(orderId);
        if (licenceOrderDetail != null) {
            //查询订单进度表
            LicenceOrderDTO licenceOrderDTO = JSONObject.parseObject(JSONObject.toJSONString(licenceOrderDetail), LicenceOrderDTO.class);
            List<TabHaobanLicenceOrderProgress> list = licenceOrderProgressService.getListByOrderId(orderId, type);
            licenceOrderDTO.setOrderProgressList(EntityUtil.changeEntityListByJSON(LicenceOrderProgressDTO.class, list));
            //查询gic品牌名称
            EnterpriseDTO enterpriseDTO = enterpriseService.getEnterpriseById(licenceOrderDTO.getEnterpriseId());
            if (ObjectUtil.isNotNull(enterpriseDTO)) {
                licenceOrderDTO.setEnterpriseName(enterpriseDTO.getEnterpriseName());
            }
            WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseApiService.getOne(licenceOrderDTO.getWxEnterpriseId());
            if (ObjectUtil.isNotNull(wxEnterpriseDTO)) {
                logger.info("企业微信查询返回实体：{}", JSON.toJSONString(wxEnterpriseDTO));
                licenceOrderDTO.setWxEnterpriseName(wxEnterpriseDTO.getCorpName());
            }
            licenceOrderDTO.setNowTime(new Date());
            return ServiceResponse.success(licenceOrderDTO);
        }
        return ServiceResponse.success();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ServiceResponse<Boolean> deleteLicenceOrder(Long orderId) {
        licenceOrderService.deleteLicenceOrder(orderId);
        licenceOrderProgressService.deleteByOrderId(orderId);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<String> saveOrUpdateLicenceOrder(LicenceOrderQDTO licenceOrderQDTO) {
        String s = licenceOrderService.saveOrUpdateLicenceOrder(licenceOrderQDTO);
        return ServiceResponse.success(s);
    }

    @Override
    public ServiceResponse<Page<LicenceOrderPageDTO>> getLicenceOrderPage(LicenceOrderPageQDTO licenceOrderPageQDTO) {
        Page<LicenceOrderPageDTO> licenceOrderPage = licenceOrderService.getLicenceOrderPage(licenceOrderPageQDTO);
        return ServiceResponse.success(licenceOrderPage);
    }

    @Override
    public ServiceResponse<Boolean> updateLicenceOrderType(Long orderId, Integer type, String enterpriseId, String wxEnterpriseId, String creatorName, Integer wxFlag) {
        licenceOrderService.updateLicenceOrderType(orderId, type, enterpriseId, wxEnterpriseId, creatorName, wxFlag);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<Boolean> uploadLicenceOrderVoucher(Long orderId, String voucher, String enterpriseId, String wxEnterpriseId, String creatorName) {
        licenceOrderService.uploadLicenceOrderVoucher(orderId, voucher, enterpriseId, wxEnterpriseId, creatorName);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<String> payLicenceOrder(Long orderId) {
        TabHaobanLicenceOrder order = licenceOrderService.getLicenceOrderDetail(orderId);
        if (order == null) {
            return ServiceResponse.failure("-9999", "参数有误！！");
        }
        WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseService.selectById(order.getWxEnterpriseId());
        if (wxEnterpriseDTO == null) {
            return ServiceResponse.failure("-9999", "微信企业不存在！！");
        }
        String openCorpid = wxEnterpriseDTO.getOpenCorpid();
        String serviceCorpid = config.getCorpid();
        //需要先判断是否已经下单，且订单失效的话重新下单
        if (null != order.getQywxOrderId()) {
            FeeOrderDeatilResponseDTO dto = qywxUserApiService.getOrder(openCorpid, serviceCorpid, order.getQywxOrderId());
            if (null != dto && null != dto.getOrder() && dto.getOrder().getOrderStatus() != 3){
                //企业微信订单有效，无需重复创建
                return ServiceResponse.success(order.getQywxOrderId());
            }
            if (null != dto && null != dto.getOrder() && dto.getOrder().getOrderStatus() == 3){
                //订单失效，记录企业微信订单状态
                licenceOrderService.updateLicenceOrderType(order.getOrderId(), 3, order.getEnterpriseId(),
                        order.getWxEnterpriseId(), "系统", 0);
            }
        }
        //创建企业微信订单
        CreateOrderQDTO orderQDTO = new CreateOrderQDTO();
        orderQDTO.setBaseCount(0);
        orderQDTO.setExternalCount(order.getExternalContactCount());
        orderQDTO.setBuyerUserid(config.getBuyerUserid());
        if (order.getTimeType() == 1) {
            orderQDTO.setMonths(order.getTimeValue());
            orderQDTO.setDays(0);
        } else {
            orderQDTO.setMonths(0);
            orderQDTO.setDays(order.getTimeValue());
        }
        ServiceResponse<CreateOrderResponseDTO> newOrder = qywxOrderApiService.createNewOrder(serviceCorpid, openCorpid, orderQDTO);
        logger.info("企业微信订单返回信息：{}", JSON.toJSONString(newOrder));
        if (newOrder.isSuccess()) {
            //更新企业微信订单状态，保存企业微信订单id
            CreateOrderResponseDTO result = newOrder.getResult();
            licenceOrderService.updateLicenceOrderType(order.getOrderId(), 0, order.getEnterpriseId(),
                    order.getWxEnterpriseId(), "系统", 0);

            licenceOrderService.saveQywxOrderId(order.getOrderId(), result.getOrderId());
            return ServiceResponse.success(result.getOrderId());
        }
        return ServiceResponse.failure(newOrder.getCode(), newOrder.getMessage());
    }

    @Override
    public ServiceResponse<String> isPayLicenceOrder(String wxEnterpriseId) {
        String order = licenceOrderService.isPayLicenceOrder(wxEnterpriseId);
        return ServiceResponse.success(order);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ServiceResponse<Boolean> wxCallBack(String params) {
        logger.info("接收微信回调参数：{}", params);
        if (StrUtil.isBlank(params)) {
            return ServiceResponse.success(false);
        }
        JSONObject object = JSONObject.parseObject(params, JSONObject.class);
        //微信的订单id，保留方便后续对账
        String orderId = object.getString("orderId");
        String transactionId = object.getString("transactionId");
        String timeEnd = object.getString("timeEnd");
        //对同一笔订单上锁
        String key = "haoban_wx_licence_order_+"+transactionId;
        RedisUtil.lock(key,2L);
        TabHaobanLicenceOrder licenceOrder = licenceOrderService.selectByTransactionId(orderId);
        if (licenceOrder == null) {
            logger.info("微信回调的订单编号：{}异常！！", orderId);
            RedisUtil.unlock(key);
            return ServiceResponse.success(false);
        }
        if (licenceOrder.getOrderStatus() == 1) {
            //微信会多次回调
            logger.info("微信回调的订单已处理！");
            RedisUtil.unlock(key);
            return ServiceResponse.success(false);
        }
        Date payTime = DateUtil.strToDate(timeEnd,DateUtil.FORMAT_DATETIME_14);
        //更新订单状态
        licenceOrderService.updateLicenceOrderType(licenceOrder.getOrderId(), 1, licenceOrder.getEnterpriseId(), licenceOrder.getWxEnterpriseId(), "系统", 1);
        //保存微信订单id
        licenceOrderService.saveTransactionCode(licenceOrder.getOrderId(), null, null, transactionId, payTime,null);
        RedisUtil.unlock(key);
        //查询gic品牌名称
        String enterpriseName = "";
        String wxEnterpriseName = "";
        EnterpriseDTO enterpriseDTO = enterpriseService.getEnterpriseById(licenceOrder.getEnterpriseId());
        if (ObjectUtil.isNotNull(enterpriseDTO)) {
            enterpriseName = enterpriseDTO.getEnterpriseName();
        }
        WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseApiService.getOne(licenceOrder.getWxEnterpriseId());
        if (ObjectUtil.isNotNull(wxEnterpriseDTO)) {
            wxEnterpriseName = wxEnterpriseDTO.getCorpName();
        }
        String dateToStr = DateUtil.dateToStr(new Date(), DateUtil.FORMAT_DATETIME_19);
        //发送钉钉消息通知
        String host = config.getHost();
        //拿到钉钉群机器人url
        String dingUrl = config.getDingUrl();
        // 最后一个分隔符位置
        int lastIndex = host.lastIndexOf("/");
        // 倒数第二个分隔符位置
        int secondLastIndex = host.lastIndexOf("/", lastIndex - 1);
        String subHost = host.substring(0, secondLastIndex + 1);
        String url = subHost + "enterprise-operation/#/finance-config/wx-order-detail?tabId=wx_account_order&orderId=" + licenceOrder.getOrderId();
        String msg = "标题：企微账号许可通知\n品牌名称：" + enterpriseName + "\n" + "企业名称：" + wxEnterpriseName + "\n" + "消息内容：" + dateToStr +
                "新增订单（编号：" + licenceOrder.getOrderNumber() + "）,请尽快处理！\n" + url;
        DingUtils.send(msg, dingUrl, false);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<Boolean> qywxCallBack(String params) {
        logger.info("接收企业微信回调参数：{}", JSON.toJSONString(params));
        if (StrUtil.isBlank(params)) {
            return ServiceResponse.success(false);
        }
        JSONObject object = JSONObject.parseObject(params, JSONObject.class);
        String infoType = object.getString("infoType");
        String openCorpId = object.getString("openCorpId");
        String orderId = object.getString("orderId");
        String timeStamp = object.getString("timeStamp");
        Integer orderStatus = object.getInteger("orderStatus");
        //对同一笔订单上锁
        String key = "haoban_qywx_licence_order_+"+orderId;
        RedisUtil.lock(key,2L);
        TabHaobanLicenceOrder order = licenceOrderService.selectByQywxOrderId(orderId);
        //将秒级时间戳转换位Date类型
        SimpleDateFormat formatter = new SimpleDateFormat(DateUtil.FORMAT_DATETIME_19);
        String date_time = formatter.format(new Date(Long.valueOf(timeStamp) * 1000L));
        Date date = DateUtil.strToDate(date_time, DateUtil.FORMAT_DATETIME_19);
        if (order == null) {
            RedisUtil.unlock(key);
            return ServiceResponse.success(false);
        }
        if ("license_pay_success".equals(infoType)) {
            if (order.getQywxPayTime() != null) {
                //该笔订单已处理
                RedisUtil.unlock(key);
                return ServiceResponse.success(false);
            }
            //更新企业微信订单状态
            licenceOrderService.updateLicenceOrderType(order.getOrderId(), 1, order.getEnterpriseId(), order.getWxEnterpriseId(), "系统", 0);
            //记录支付时间
            licenceOrderService.saveCallBackTime(order.getOrderId(), 2, date);
        }
        if ("license_refund".equals(infoType)) {
            if (order.getQywxRefundTime() != null) {
                //该笔订单已处理
                RedisUtil.unlock(key);
                return ServiceResponse.success(false);
            }
            //退款回调 订单状态，1:退款成功，2:退款被拒绝。
            if (orderStatus == 1) {
                licenceOrderService.updateLicenceOrderType(order.getOrderId(), 6, order.getEnterpriseId(), order.getWxEnterpriseId(), "系统", 0);
                //记录退款时间
                licenceOrderService.saveCallBackTime(order.getOrderId(), 3, date);
                wxRefund(order.getOrderId());

            } else if (orderStatus == 2) {
                licenceOrderService.updateLicenceOrderType(order.getOrderId(), 5, order.getEnterpriseId(), order.getWxEnterpriseId(), "系统", 0);
                //记录退款时间
                licenceOrderService.saveCallBackTime(order.getOrderId(), 3, date);
            }
        }
        RedisUtil.unlock(key);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<Boolean> saveTransactionCode(Long orderId, String transactionCode, String prepayId, String wxOrderId, Date payTime,String wxUrl) {
        licenceOrderService.saveTransactionCode(orderId, transactionCode, prepayId, wxOrderId, payTime,wxUrl);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<List<String>> getOrderIdList(String param, Integer type, String wxEnterpriseId) {
        return ServiceResponse.success(licenceOrderService.getOrderIdList(param, type, wxEnterpriseId));
    }

    @Override
    public ServiceResponse<Boolean> checkLicenceOrder(Long orderId, Integer flag, String reason, String creatorName) {
        licenceOrderService.checkLicenceOrder(orderId, flag, reason,creatorName);
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<Boolean> wxRefund(Long orderId) {
        TabHaobanLicenceOrder order = licenceOrderService.getLicenceOrderDetail(orderId);
        if (null == order) {
            return ServiceResponse.failure("-9999", "订单id有误！");
        }
        if (2 == order.getPayType()) {
            //对公转账不需要微信退款，直接更新微信订单状态
            licenceOrderService.updateLicenceOrderType(order.getOrderId(), 4, order.getEnterpriseId(), order.getWxEnterpriseId(), "系统", 1);
            return ServiceResponse.success(true);
        }
        if (4 == order.getOrderStatus()){
            return ServiceResponse.failure("-9999", "该笔订单已退款！");
        }
        RefundReqDataDTO reqData = new RefundReqDataDTO(order.getWxOrderId(), null, null, String.valueOf(orderId), order.getPrice(),
                order.getPrice(), null, null);
        RefundResDataDTO refund = pay4WXService.refund(reqData);
        logger.info("微信订单退款返回信息：{}",JSON.toJSONString(refund));
        if (refund != null && ("FAIL".equals(refund.getReturn_code()) || "FAIL".equals(refund.getResult_code()))) {
            //微信退款失败，钉钉通知财务人员
            //查询gic品牌名称
            String enterpriseName = "";
            String wxEnterpriseName = "";
            EnterpriseDTO enterpriseDTO = enterpriseService.getEnterpriseById(order.getEnterpriseId());
            if (ObjectUtil.isNotNull(enterpriseDTO)) {
                enterpriseName = enterpriseDTO.getEnterpriseName();
            }
            WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseApiService.getOne(order.getWxEnterpriseId());
            if (ObjectUtil.isNotNull(wxEnterpriseDTO)) {
                wxEnterpriseName = wxEnterpriseDTO.getCorpName();
            }
            //发送钉钉消息通知
            String host = config.getHost();
            //拿到钉钉群机器人url
            String dingUrl = config.getDingUrl();
            // 最后一个分隔符位置
            int lastIndex = host.lastIndexOf("/");
            // 倒数第二个分隔符位置
            int secondLastIndex = host.lastIndexOf("/", lastIndex - 1);
            String subHost = host.substring(0, secondLastIndex + 1);
            String url = subHost + "enterprise-operation/#/finance-config/wx-order-detail?tabId=wx_account_order&orderId=" + order.getOrderId();
            String msg = "标题：企微账号许可通知\n品牌名称：" + enterpriseName + "\n" + "企业名称：" + wxEnterpriseName + "\n" + "消息内容：订单编号："+order.getOrderNumber()
                    +",申请微信退款失败，请查看原因并处理！\n"+"失败原因："+refund.getErr_code_des()+"\n" + url;
            DingUtils.send(msg, dingUrl, false);
            return ServiceResponse.failure(refund.getResult_code(), refund.getErr_code_des());
        }
        //更新微信订单状态
        licenceOrderService.updateLicenceOrderType(order.getOrderId(), 4, order.getEnterpriseId(), order.getWxEnterpriseId(), "系统", 1);
        //记录支付时间
        licenceOrderService.saveCallBackTime(order.getOrderId(), 1, new Date());
        return ServiceResponse.success(true);
    }

    @Override
    public ServiceResponse<HashMap<String, String>> getAccountInfo() {
        HashMap<String, String> result = new HashMap<>(8);
        result.put("accountName",config.getAccountName());
        result.put("accountNumber",config.getAccountNumber());
        result.put("bankName",config.getBankName());
        return ServiceResponse.success(result);
    }

    @Override
    public ServiceResponse<Boolean> cancelQywxOrder(Long orderId) {
        TabHaobanLicenceOrder order = licenceOrderService.getLicenceOrderDetail(orderId);
        if (null == order) {
            return ServiceResponse.failure("-9999", "订单id有误！");
        }
        //企业微信订单取消
        WxEnterpriseDTO wxEnterpriseDTO = wxEnterpriseService.selectById(order.getWxEnterpriseId());
        if (wxEnterpriseDTO == null) {
            return ServiceResponse.failure("-9999", "微信企业不存在！！");
        }
        //先申请微信退款，再取消企业微信订单
        wxRefund(orderId);
        String openCorpid = wxEnterpriseDTO.getOpenCorpid();
        String serviceCorpid = config.getCorpid();
        ServiceResponse<QywxResponseDTO> response = qywxOrderApiService.cancelOrder(serviceCorpid, openCorpid, order.getQywxOrderId());
        logger.info("企业微信订单取消返回信息：{}",JSON.toJSONString(response));
        if (response.isSuccess()){
            //更新企业微信订单状态
            updateLicenceOrderType(orderId, 2, order.getEnterpriseId(), order.getWxEnterpriseId(), order.getCreatorName(), 0);
            return ServiceResponse.success(true);
        }
        return ServiceResponse.failure(response.getCode(),response.getMessage());
    }

    @Override
    public ServiceResponse<HashMap<String, Integer>> hasPopup(String wxEnterpriseId) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("hasPopup",0);
        map.put("count",0);
        List<String> list = staffClerkRelationService.listByWxEnterpriseId(wxEnterpriseId);
        if (CollUtil.isEmpty(list)){
            return ServiceResponse.success(map);
        }
        //去重
        list = list.stream().distinct().collect(Collectors.toList());
        Integer count = licenceOrderService.selectCountByWxEnterpriseId(wxEnterpriseId);
        if (count==0){
            StaffActiveDataDTO dto  = wxEnterpriseActiveDataService.getWxEnterpriseActiveDataByWxEnterpriseId(wxEnterpriseId);
            if (null != dto && dto.getPurchased()!=null && dto.getPurchased() > 0){
                return ServiceResponse.success(map);
            }
            map.put("hasPopup",1);
            map.put("count",list.size());
            return ServiceResponse.success(map);
        }
        return ServiceResponse.success(map);
    }

}
