package com.jeequan.jeepay.mch.ctrl.plugin;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.device.PluginCdKeyParams;
import com.jeequan.jeepay.core.model.device.PluginProviderParams;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 收银插件 接口管理类
 *
 * @author zx
 *
 * @date 2022/3/4 9:43
 */
@Slf4j
@RestController
@RequestMapping("/api/anon/cashier")
public class PluginController extends CommonCtrl {

    @Autowired private DeviceProvideConfigService deviceProvideConfigService;
    @Autowired private MchStoreDeviceService mchStoreDeviceService;
    @Autowired private MchInfoService mchInfoService;
    @Autowired private MchStoreService mchStoreService;
    @Autowired private MchAppService mchAppService;
    @Autowired private PayOrderService payOrderService;
    @Autowired private RefundOrderService refundOrderService;
    @Autowired private PayWayService payWayService;

    /** 激活码  激活 **/
    @PostMapping("/pluginActive/{cdKey}")
    public ApiRes init(@PathVariable("cdKey") String cdKey) {

        // 验证appSecret
        DeviceProvideConfig provideConfig = checkAppSecret();
        // 激活码对象
        MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, true);
        // 激活码详细参数
        PluginCdKeyParams cdKeyParams = JSONObject.parseObject(mchStoreDevice.getDeviceParams(), PluginCdKeyParams.class);

        // 更新对象
        MchStoreDevice updateRecord = new MchStoreDevice();
        updateRecord.setState(CS.YES); // 已激活
        cdKeyParams.setActiveTime(DateUtil.now()); // 激活时间
        cdKeyParams.setDeActiveTime(""); // 解除激活时间置空
        updateRecord.setDeviceParams(JSONObject.toJSONString(cdKeyParams));

        // 更新操作
        boolean result = mchStoreDeviceService.update(updateRecord, new LambdaUpdateWrapper<MchStoreDevice>()
                .eq(MchStoreDevice::getDeviceId, mchStoreDevice.getDeviceId())
                .eq(MchStoreDevice::getState, CS.NO)
        );
        if (!result) {
            return ApiRes.fail(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
        }

        return ApiRes.ok(genCdkeyParams(mchStoreDevice, cdKeyParams, provideConfig));
    }

    /** 激活码查询 **/
    @GetMapping("/plugin/{cdKey}")
    public ApiRes detail(@PathVariable("cdKey") String cdKey) {

        // 验证appSecret
        DeviceProvideConfig provideConfig = checkAppSecret();
        // 激活码对象
        MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);
        // 激活码详细参数
        PluginCdKeyParams cdKeyParams = JSONObject.parseObject(mchStoreDevice.getDeviceParams(), PluginCdKeyParams.class);

        return ApiRes.ok(genCdkeyParams(mchStoreDevice, cdKeyParams, provideConfig));
    }

    /** 校验appSecret **/
    private DeviceProvideConfig checkAppSecret() {
        String appSecret = request.getHeader("appSecret");
        if (StringUtils.isBlank(appSecret)) {
            throw new BizException("非法请求");
        }

        DeviceProvideConfig provideConfig = deviceProvideConfigService.getOneByAppId(appSecret);
        if (provideConfig == null || provideConfig.getState() == CS.NO || StringUtils.isBlank(provideConfig.getProviderParams())) {
            throw new BizException("非法请求");
        }
        return provideConfig;
    }

    /** 汇总查询 **/
    @GetMapping("/statictics/{cdKey}")
    public ApiRes statictics(@PathVariable("cdKey") String cdKey) {

        // 验证appSecret
        DeviceProvideConfig provideConfig = checkAppSecret();
        // 激活码对象
        MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);

        JSONObject paramJSON = getReqParamJSON();
        PayOrder payOrder = getObject(PayOrder.class);
        payOrder.setMchNo(mchStoreDevice.getMchNo());
        payOrder.setStoreId(mchStoreDevice.getStoreId());
        payOrder.setAppId(mchStoreDevice.getAppId());

        PayOrderCount orderCount = payOrderService.orderCount(payOrder, paramJSON, null);

        // 支付类型
        Page<PayOrderCount> mapPage = payOrderService.countListByWayCodeType(payOrder, paramJSON);
        if (CollUtil.isNotEmpty(mapPage.getRecords())) {
            mapPage.getRecords().forEach(map -> {
                String wayType = map.getWayType();
                //TODO 需要修改
//                orderCount.put((String) map.get("wayType"), map);
            });
        }

        return ApiRes.ok(orderCount);
    }

    /** 支付订单查询 **/
    @GetMapping("/payList/{cdKey}")
    public ApiRes payList(@PathVariable("cdKey") String cdKey) {

        // 验证appSecret
        DeviceProvideConfig provideConfig = checkAppSecret();
        // 激活码对象
        MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);

        JSONObject paramJSON = getReqParamJSON();
        PayOrder payOrder = getObject(PayOrder.class);
        payOrder.setMchNo(mchStoreDevice.getMchNo());
        payOrder.setStoreId(mchStoreDevice.getStoreId());
        payOrder.setAppId(mchStoreDevice.getAppId());


        IPage<PayOrder> pages = payOrderService.listByPage(getIPage(), payOrder, paramJSON);

        return ApiRes.page(pages);
    }

    /** 退款订单查询 **/
    @GetMapping("/refundList/{cdKey}")
    public ApiRes refundList(@PathVariable("cdKey") String cdKey) {

        // 验证appSecret
        DeviceProvideConfig provideConfig = checkAppSecret();
        // 激活码对象
        MchStoreDevice mchStoreDevice = checkCdKey(provideConfig.getProvider(), cdKey, false);

        JSONObject paramJSON = getReqParamJSON();
        RefundOrder refundOrder = getObject(RefundOrder.class);
        refundOrder.setMchNo(mchStoreDevice.getMchNo());
        refundOrder.setStoreId(mchStoreDevice.getStoreId());
        refundOrder.setAppId(mchStoreDevice.getAppId());

        LambdaQueryWrapper<RefundOrder> gw = RefundOrder.gw();
        gw.select(RefundOrder::getRefundOrderId, RefundOrder::getPayOrderId, RefundOrder::getMchRefundNo, RefundOrder::getState, RefundOrder::getRefundAmount, RefundOrder::getMchNo, RefundOrder::getMchName,
                RefundOrder::getStoreId, RefundOrder::getStoreName, RefundOrder::getAppId, RefundOrder::getMchRefundNo, RefundOrder::getWayCode, RefundOrder::getPayAmount,
                RefundOrder::getRefundReason, RefundOrder::getSuccessTime, RefundOrder::getExpiredTime, RefundOrder::getCreatedAt);

        IPage<RefundOrder> pages = refundOrderService.pageList(getIPage(), gw, refundOrder, paramJSON);

        // 得到所有支付方式
        Map<String, PayWay> payWayMap = new HashMap<>();
        List<PayWay> payWayList = payWayService.list();
        if (!CollectionUtils.isEmpty(payWayList)) {
            for (PayWay payWay:payWayList) {
                payWayMap.put(payWay.getWayCode(), payWay);
            }
            for (RefundOrder order:pages.getRecords()) {
                // 存入支付方式名称
                if (payWayMap.get(order.getWayCode()) != null) {
                    order.addExt("wayName", payWayMap.get(order.getWayCode()).getWayName());
                    order.addExt("wayCodeType", payWayMap.get(order.getWayCode()).getWayType());
                }else {
                    order.addExt("wayName", order.getWayCode());
                }
            }
        }

        return ApiRes.page(pages);
    }

    /** 校验cdKey **/
    private MchStoreDevice checkCdKey(String provider, String cdKey, boolean isInit) {
        MchStoreDevice mchStoreDevice = mchStoreDeviceService.getOne(MchStoreDevice.gw()
                .eq(MchStoreDevice::getDeviceType, MchStoreDevice.DEVICE_TYPE_PLUGIN)
                .eq(MchStoreDevice::getProvider, provider)
                .eq(MchStoreDevice::getDeviceNo, cdKey)
        );
        // 激活码不存在 || 已激活 || 未绑定 || 无参数
        if (mchStoreDevice == null || mchStoreDevice.getBindState() == CS.NO || StringUtils.isBlank(mchStoreDevice.getDeviceParams())) {
            throw new BizException("激活码无效");
        }
        if (isInit && mchStoreDevice.getState() == CS.YES) {
            throw new BizException("激活码无效");
        }else if (!isInit && mchStoreDevice.getState() == CS.NO) {
            throw new BizException("激活码无效");
        }

        PluginCdKeyParams cdKeyParams = JSONObject.parseObject(mchStoreDevice.getDeviceParams(), PluginCdKeyParams.class);
        // 激活码已失效
        if (cdKeyParams == null || StringUtils.isAnyBlank(cdKeyParams.getCdKey(), cdKeyParams.getExpiredTime())
                || (!StringUtils.equals("0", cdKeyParams.getExpiredTime()) && DateUtil.compare(new Date(), DateUtil.parseDate(cdKeyParams.getExpiredTime())) > 0)) {
            throw new BizException("激活码无效");
        }
        return mchStoreDevice;
    }

    /** 返回的 激活码对象 **/
    private JSONObject genCdkeyParams(MchStoreDevice mchStoreDevice, PluginCdKeyParams cdKeyParams, DeviceProvideConfig provideConfig) {
        MchInfo mchInfo = mchInfoService.getById(mchStoreDevice.getMchNo());
        MchStore mchStore = mchStoreService.getById(mchStoreDevice.getStoreId());
        MchAppEntity mchAppEntity = mchAppService.getById(mchStoreDevice.getAppId());
        if (mchInfo == null || mchStore == null || mchAppEntity == null) {
            throw new BizException("系统异常");
        }

        PluginProviderParams providerParams = JSONObject.parseObject(provideConfig.getProviderParams(), PluginProviderParams.class);
        if (providerParams == null) {
            throw new BizException("厂商");
        }

        // 返回数据
        JSONObject resJSON = new JSONObject();
        resJSON.put("provider", mchStoreDevice.getProvider()); // 厂商
        resJSON.put("subject", StringUtils.isBlank(providerParams.getSubject()) ? "收银插件收款" : providerParams.getSubject()); // 默认商品标题
        resJSON.put("body",  StringUtils.isBlank(providerParams.getBody()) ? "收银插件收款" : providerParams.getBody()); // 默认商品描述
        resJSON.put("cdKey", mchStoreDevice.getDeviceNo()); // 激活码
        resJSON.put("activeTime", cdKeyParams.getActiveTime()); // 激活时间
        resJSON.put("expiredTime", cdKeyParams.getExpiredTime()); // 有效期
        resJSON.put("mchNo", mchStoreDevice.getMchNo()); // 商户号
        resJSON.put("mchName", mchInfo.getMchName()); // 商户名称
        resJSON.put("storeId", mchStoreDevice.getStoreId()); // 门店ID
        resJSON.put("storeName", mchStore.getStoreName()); // 门店名称
        resJSON.put("appId", mchStoreDevice.getAppId()); // 应用appId
        resJSON.put("appName", mchAppEntity.getAppName()); // 应用名称
        resJSON.put("appSignType", mchAppEntity.getAppSignType()); // 签名方式
        resJSON.put("appSecret", mchAppEntity.getAppSecret()); // 应用私钥
        resJSON.put("state", CS.YES); // 激活状态
        resJSON.put("payUrl", sysConfigService.getDBApplicationConfig().getPaySiteUrl()); // 支付网关地址
        return resJSON;
    }

}
