package com.zanxiang.game.module.manage.service.impl;

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.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.erp.security.util.SecurityUtil;
import com.zanxiang.game.module.base.pojo.enums.DeleteEnum;
import com.zanxiang.game.module.base.pojo.enums.PayDeviceEnum;
import com.zanxiang.game.module.base.pojo.enums.PayWayEnum;
import com.zanxiang.game.module.base.pojo.enums.StatusEnum;
import com.zanxiang.game.module.base.util.DateUtils;
import com.zanxiang.game.module.manage.pojo.dto.PayMerchantDTO;
import com.zanxiang.game.module.manage.pojo.params.PayMerchantAddUpdateParam;
import com.zanxiang.game.module.manage.pojo.params.PayMerchantListParam;
import com.zanxiang.game.module.manage.pojo.vo.PayMerchantChoiceVO;
import com.zanxiang.game.module.manage.pojo.vo.PayMerchantListVO;
import com.zanxiang.game.module.manage.service.IPayMerchantService;
import com.zanxiang.game.module.mybatis.entity.PayMerchant;
import com.zanxiang.game.module.mybatis.mapper.PayMerchantMapper;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.bean.BeanUtil;
import com.zanxiang.module.util.exception.BaseException;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2022-11-25
 * @description : 商户管理
 */
@Service
public class PayMerchantServiceImpl extends ServiceImpl<PayMerchantMapper, PayMerchant> implements IPayMerchantService {

    @Override
    public boolean addOrUpdate(PayMerchantAddUpdateParam param) {
        String payDeviceIds = null;
        if (CollectionUtils.isNotEmpty(param.getPayDeviceIdList())) {
            payDeviceIds = param.getPayDeviceIdList().stream()
                    .map(String::valueOf).collect(Collectors.joining(","));
        }
        String payConfig = null;
        if (Strings.isNotBlank(param.getSecretKey())) {
            Map<String, String> configMap = new HashMap<>(4);
            if (Objects.equals(param.getPayWayId().intValue(), PayWayEnum.ALI_PAY.getPayWayId())) {
                configMap.put("protocol", "https");
                configMap.put("gatewayHost", "openapi.alipay.com");
                configMap.put("signType", "RSA2");
                configMap.put("alipayPublicKey", param.getSecretKey());
            }
            if (Objects.equals(param.getPayWayId().intValue(), PayWayEnum.WX_PAY.getPayWayId())) {
                configMap.put("mchId", param.getMerchantNo());
                configMap.put("apiKey", param.getSecretKey());
                configMap.put("signType", "MD5");
            }
            payConfig = JsonUtil.toString(configMap);
        }
        Long id = param.getId();
        if (id == null) {
            return super.save(this.transform(param, payConfig, payDeviceIds));
        }
        PayMerchant payMerchant = super.getById(id);
        if (payMerchant == null) {
            throw new BaseException("参数错误, 商户信息不存在");
        }
        //商户号更新, 判断是否已经存在商户号
        if (!Objects.equals(payMerchant.getMerchantNo(), param.getMerchantNo())
                && super.count(new LambdaQueryWrapper<PayMerchant>()
                .eq(PayMerchant::getMerchantNo, param.getMerchantNo())) > 0) {
            throw new BaseException("参数错误, 商户号已经存在, 不可更新为该商户号");
        }
        payMerchant.setMerchantNo(param.getMerchantNo());
        payMerchant.setMerchantName(param.getMerchantName());
        payMerchant.setMerchantCompany(param.getMerchantCompany());
        payMerchant.setPayWayId(param.getPayWayId());
        payMerchant.setAccount(param.getAccount());
        payMerchant.setPassword(param.getPassword());
        payMerchant.setManager(param.getManager());
        payMerchant.setMobile(param.getMobile());
        payMerchant.setEmail(param.getEmail());
        payMerchant.setPayConfig(payConfig);
        payMerchant.setRemark(param.getRemark());
        payMerchant.setPayDeviceIds(payDeviceIds);
        payMerchant.setUpdateById(SecurityUtil.getUserId());
        payMerchant.setUpdateTime(LocalDateTime.now());
        return super.updateById(payMerchant);
    }

    private PayMerchant transform(PayMerchantAddUpdateParam param, String payConfig, String payDeviceIds) {
        return PayMerchant.builder()
                .merchantNo(param.getMerchantNo())
                .merchantName(param.getMerchantName())
                .merchantCompany(param.getMerchantCompany())
                .payWayId(param.getPayWayId())
                .account(param.getAccount())
                .password(param.getPassword())
                .manager(param.getManager())
                .mobile(param.getMobile())
                .email(param.getEmail())
                .payConfig(payConfig)
                .maxPayLock(StatusEnum.YES.getCode())
                .remark(param.getRemark())
                .status(StatusEnum.YES.getCode())
                .isDelete(DeleteEnum.NO.getCode())
                .createById(SecurityUtil.getUserId())
                .createTime(LocalDateTime.now())
                .updateById(SecurityUtil.getUserId())
                .updateTime(LocalDateTime.now())
                .payDeviceIds(payDeviceIds)
                .build();
    }

    @Override
    public List<PayMerchantChoiceVO> payMerchantChoiceList() {
        return super.list(new LambdaQueryWrapper<PayMerchant>()
                .select(PayMerchant::getMerchantNo, PayMerchant::getPayWayId, PayMerchant::getMerchantName))
                .stream()
                .map(payMerchant -> BeanUtil.copy(payMerchant, PayMerchantChoiceVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public IPage<PayMerchantListVO> pageList(PayMerchantListParam param) {
        //查询
        return page(param.toPage(), new LambdaQueryWrapper<PayMerchant>()
                .eq(param.getMerchantNo() != null, PayMerchant::getMerchantNo, param.getMerchantNo())
                .eq(param.getPayWayId() != null, PayMerchant::getPayWayId, param.getPayWayId())
                .eq(param.getStatus() != null, PayMerchant::getStatus, param.getStatus())
                .like(Strings.isNotBlank(param.getMerchantName()), PayMerchant::getMerchantName, param.getMerchantName())
                .orderByDesc(PayMerchant::getCreateTime))
                .convert(this::toVo);
    }

    private PayMerchantListVO toVo(PayMerchant payMerchant) {
        PayMerchantListVO payMerchantListVO = BeanUtil.copy(payMerchant, PayMerchantListVO.class);
        if (payMerchantListVO == null) {
            return null;
        }
        //判断月更新日期是否为本月
        if (!DateUtils.isThisMonth(payMerchant.getMouthUpdateDate())) {
            //月已用额度归零
            payMerchantListVO.setMouthPayAmount(BigDecimal.ZERO);
        }
        //判断日更新日期是否为今天
        if (!DateUtils.isToday(payMerchant.getDayUpdateDate())) {
            //日已用额度归零
            payMerchantListVO.setDayPayAmount(BigDecimal.ZERO);
        }
        //判断周更新日期是否为本周
        if (!DateUtils.isThisWeek(payMerchant.getMouthUpdateDate())) {
            //周已用额度归零
            payMerchantListVO.setWeakerPayAmount(BigDecimal.ZERO);
        }
        //密钥
        if (Strings.isNotBlank(payMerchant.getPayConfig())) {
            Map<String, String> payConfigMap = JsonUtil.toMap(payMerchant.getPayConfig(), Map.class, String.class);
            if (Objects.equals(payMerchant.getPayWayId().intValue(), PayWayEnum.ALI_PAY.getPayWayId())) {
                payMerchantListVO.setSecretKey(payConfigMap.get("alipayPublicKey"));
            }
            if (Objects.equals(payMerchant.getPayWayId().intValue(), PayWayEnum.WX_PAY.getPayWayId())) {
                payMerchantListVO.setSecretKey(payConfigMap.get("apiKey"));
            }
        }
        //支付渠道
        payMerchantListVO.setPayWayName(PayWayEnum.getNameByPayWayId(payMerchantListVO.getPayWayId()));
        //支付方式
        String payDeviceIds = payMerchant.getPayDeviceIds();
        if (Strings.isBlank(payDeviceIds)) {
            return payMerchantListVO;
        }
        payMerchantListVO.setPayDeviceIdList(new ArrayList<>());
        payMerchantListVO.setPayDeviceNameList(new ArrayList<>());
        String[] deviceIdArray = payDeviceIds.split(",");
        for (String deviceId : deviceIdArray) {
            PayDeviceEnum payDeviceEnum = PayDeviceEnum.getPayDeviceEnum(Long.valueOf(deviceId));
            if (payDeviceEnum != null) {
                payMerchantListVO.getPayDeviceIdList().add(payDeviceEnum.getPayDeviceId());
                payMerchantListVO.getPayDeviceNameList().add(payDeviceEnum.getPayDeviceName());
            }
        }
        return payMerchantListVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean statusUpdate(Long id, Integer status) {
        return super.update(new LambdaUpdateWrapper<PayMerchant>()
                .set(PayMerchant::getStatus, status)
                .set(PayMerchant::getUpdateTime, LocalDateTime.now())
                .eq(PayMerchant::getId, id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean secretKeyUpdate(Long id, String secretKey) {
        PayMerchant payMerchant = super.getById(id);
        if (payMerchant == null) {
            throw new BaseException("参数错误, 商户信息不存在");
        }
        Map<String, String> configMap = new HashMap<>(4);
        if (Objects.equals(payMerchant.getPayWayId().intValue(), PayWayEnum.ALI_PAY.getPayWayId())) {
            configMap.put("protocol", "https");
            configMap.put("gatewayHost", "openapi.alipay.com");
            configMap.put("signType", "RSA2");
            configMap.put("alipayPublicKey", secretKey);
        }
        if (Objects.equals(payMerchant.getPayWayId().intValue(), PayWayEnum.WX_PAY.getPayWayId())) {
            configMap.put("mchId", payMerchant.getMerchantNo());
            configMap.put("apiKey", secretKey);
            configMap.put("signType", "MD5");
        }
        payMerchant.setPayConfig(JsonUtil.toString(configMap));
        return super.updateById(payMerchant);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        return super.removeById(id);
    }

    @Override
    public Map<String, PayMerchantDTO> payMerchantCondition(String merchantNo, String merchantName) {
        //条件判断
        if (Strings.isBlank(merchantNo) && Strings.isBlank(merchantName)) {
            return null;
        }
        List<PayMerchant> payMerchantList = this.list(new LambdaQueryWrapper<PayMerchant>()
                .eq(Strings.isNotBlank(merchantNo), PayMerchant::getMerchantNo, merchantNo)
                .like(Strings.isNotBlank(merchantName), PayMerchant::getMerchantName, merchantName));
        if (CollectionUtils.isEmpty(payMerchantList)) {
            return Collections.emptyMap();
        }
        return payMerchantList.stream()
                .map(payMerchant -> BeanUtil.copy(payMerchant, PayMerchantDTO.class))
                .collect(Collectors.toMap(PayMerchantDTO::getMerchantNo, Function.identity()));
    }

    @Override
    public Map<String, PayMerchantDTO> payMerchantMap() {
        List<PayMerchant> payMerchantList = this.list();
        if (CollectionUtils.isEmpty(payMerchantList)) {
            return Collections.emptyMap();
        }
        return payMerchantList.stream()
                .map(payMerchant -> BeanUtil.copy(payMerchant, PayMerchantDTO.class))
                .collect(Collectors.toMap(PayMerchantDTO::getMerchantNo, Function.identity()));
    }

    @Override
    public PayMerchantDTO getByMerchantNo(String merchantNo) {
        PayMerchant payMerchant = super.getOne(new LambdaQueryWrapper<PayMerchant>()
                .eq(PayMerchant::getMerchantNo, merchantNo));
        if (payMerchant == null) {
            return null;
        }
        return BeanUtil.copy(payMerchant, PayMerchantDTO.class);
    }
}
