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.extension.service.impl.ServiceImpl;
import com.zanxiang.game.module.base.pojo.enums.DeleteEnum;
import com.zanxiang.game.module.base.pojo.enums.PayApplicationTypeEnum;
import com.zanxiang.game.module.base.pojo.enums.StatusEnum;
import com.zanxiang.game.module.manage.pojo.dto.PayApplicationDTO;
import com.zanxiang.game.module.manage.pojo.params.PayApplicationAddUpdateParam;
import com.zanxiang.game.module.manage.pojo.params.PayApplicationListParam;
import com.zanxiang.game.module.manage.pojo.vo.PayApplicationChoiceVO;
import com.zanxiang.game.module.manage.pojo.vo.PayApplicationVO;
import com.zanxiang.game.module.manage.service.IGameAppletService;
import com.zanxiang.game.module.manage.service.IPayApplicationService;
import com.zanxiang.game.module.manage.service.IPayBoxService;
import com.zanxiang.game.module.mybatis.entity.PayApplication;
import com.zanxiang.game.module.mybatis.entity.PayBox;
import com.zanxiang.game.module.mybatis.mapper.PayApplicationMapper;
import com.zanxiang.module.util.bean.BeanUtil;
import com.zanxiang.module.util.exception.BaseException;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2022-06-23
 * @description : 支付应用管理
 */
@Service
public class PayApplicationServiceImpl extends ServiceImpl<PayApplicationMapper, PayApplication> implements IPayApplicationService {

    @Autowired
    private IGameAppletService gameAppletService;

    @Autowired
    private IPayBoxService payBoxService;

    @Override
    public List<PayApplicationChoiceVO> payApplicationChoiceList() {
        List<PayApplication> payApplicationList = super.list(new LambdaQueryWrapper<PayApplication>()
                .select(PayApplication::getAppId, PayApplication::getType, PayApplication::getAppName)
        );
        return payApplicationList.stream()
                .map(payApplication -> BeanUtil.copy(payApplication, PayApplicationChoiceVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public IPage<PayApplicationVO> pageList(PayApplicationListParam param) {
        return page(param.toPage(), new LambdaQueryWrapper<PayApplication>()
                .like(Strings.isNotBlank(param.getName()), PayApplication::getAppName, param.getName())
                .eq(param.getType() != null, PayApplication::getType, param.getType())
                .like(Strings.isNotBlank(param.getAppId()), PayApplication::getAppId, param.getAppId())
                .like(Strings.isNotBlank(param.getCompany()), PayApplication::getCompany, param.getCompany())
                .orderByDesc(PayApplication::getCreateTime))
                .convert(this::toVo);
    }

    private PayApplicationVO toVo(PayApplication payApplication) {
        PayApplicationVO applicationVO = BeanUtil.copy(payApplication, PayApplicationVO.class);
        if (Objects.isNull(applicationVO)) {
            return null;
        }
        applicationVO.setTypeName(PayApplicationTypeEnum.getDescByType(applicationVO.getType()));
        return applicationVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addOrUpdate(PayApplicationAddUpdateParam param) {
        Long id = param.getId();
        //更新
        if (id != null) {
            PayApplication payApplication = super.getById(id);
            if (payApplication == null) {
                throw new BaseException("参数错误, 支付应用信息不存在");
            }
            //更新时, 应用id不可重复
            if (!Objects.equals(payApplication.getAppId(), param.getAppId())) {
                //判断应用是否已经存在
                long count = super.count(new LambdaQueryWrapper<PayApplication>()
                        .eq(PayApplication::getAppId, param.getAppId()));
                if (count > 0) {
                    throw new BaseException("应用id已经存在");
                }
            }
            payApplication.setAppId(param.getAppId());
            payApplication.setGhId(param.getGhId());
            payApplication.setAppName(param.getAppName());
            payApplication.setType(param.getType());
            payApplication.setAppSecret(param.getAppSecret());
            payApplication.setPath(param.getPath());
            payApplication.setMerchantNo(param.getMerchantNo());
            payApplication.setCompany(param.getCompany());
            payApplication.setAccount(param.getAccount());
            payApplication.setPassword(param.getPassword());
            payApplication.setManager(param.getManager());
            payApplication.setRemark(param.getRemark());
            payApplication.setHeadImg(param.getHeadImg());
            payApplication.setQrCode(param.getQrCode());
            payApplication.setUpdateTime(LocalDateTime.now());
            return super.updateById(payApplication);
        }
        //判断应用是否已经存在
        long count = super.count(new LambdaQueryWrapper<PayApplication>()
                .eq(PayApplication::getAppId, param.getAppId()));
        if (count > 0) {
            throw new BaseException("应用id已经存在");
        }
        //创建
        return super.save(PayApplication.builder()
                .appId(param.getAppId())
                .ghId(param.getGhId())
                .appName(param.getAppName())
                .type(param.getType())
                .appSecret(param.getAppSecret())
                .path(param.getPath())
                .merchantNo(param.getMerchantNo())
                .company(param.getCompany())
                .account(param.getAccount())
                .password(param.getPassword())
                .manager(param.getManager())
                .remark(param.getRemark())
                .headImg(param.getHeadImg())
                .qrCode(param.getQrCode())
                .status(StatusEnum.YES.getCode())
                .isDelete(DeleteEnum.NO.getCode())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build());
    }

    @Override
    public String getQrCode(Long id) {
        PayApplication payApplication = super.getById(id);
        if (payApplication == null) {
            throw new BaseException("支付应用信息不存在");
        }
        //判断是否为支付宝应用
        if (Objects.equals(payApplication.getType(), PayApplicationTypeEnum.ALI_PAY_APP.getType())) {
            throw new BaseException("支付宝应用不支持生成小程序码!");
        }
        return gameAppletService.getQrCode(payApplication.getAppId(), payApplication.getAppSecret(), payApplication.getAppName());
    }

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

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

    @Override
    public Map<String, PayApplicationDTO> payApplicationCondition(Integer payApplicationType, String payApplicationAppId, String payApplicationCompany) {
        //条件判断
        if (payApplicationType == null && Strings.isBlank(payApplicationAppId) && Strings.isBlank(payApplicationCompany)) {
            return null;
        }
        List<PayApplication> payApplicationList = this.list(new LambdaQueryWrapper<PayApplication>()
                .eq(payApplicationType != null, PayApplication::getType, payApplicationType)
                .eq(Strings.isNotBlank(payApplicationAppId), PayApplication::getAppId, payApplicationAppId)
                .like(Strings.isNotBlank(payApplicationCompany), PayApplication::getCompany, payApplicationCompany));
        if (CollectionUtils.isEmpty(payApplicationList)) {
            return Collections.emptyMap();
        }
        return payApplicationList.stream()
                .map(payApplication -> BeanUtil.copy(payApplication, PayApplicationDTO.class))
                .collect(Collectors.toMap(PayApplicationDTO::getAppId, Function.identity()));
    }

    @Override
    public Map<String, PayApplicationDTO> payApplicationMap() {
        List<PayApplication> payApplicationList = this.list();
        if (CollectionUtils.isEmpty(payApplicationList)) {
            return Collections.emptyMap();
        }
        return payApplicationList.stream().map(payApplication -> BeanUtil.copy(payApplication, PayApplicationDTO.class))
                .collect(Collectors.toMap(PayApplicationDTO::getAppId, Function.identity()));
    }

    @Override
    public PayApplicationDTO getByAppId(String appId) {
        PayApplication payApplication = super.getOne(new LambdaQueryWrapper<PayApplication>()
                .eq(PayApplication::getAppId, appId));
        if (payApplication == null) {
            throw new BaseException("参数错误, 支付应用appId对应信息不存在");
        }
        return BeanUtil.copy(payApplication, PayApplicationDTO.class);
    }

    @Override
    public PayApplicationDTO getPayApplicationByPayBoxId(Long payBoxId) {
        PayBox payBox = payBoxService.getById(payBoxId);
        PayApplication payApplication = super.getOne(new LambdaQueryWrapper<PayApplication>()
                .eq(PayApplication::getAppId, payBox.getAppId()));
        if (payApplication == null) {
            throw new BaseException("参数错误, 支付商城小程序信息不存在");
        }
        return BeanUtil.copy(payApplication, PayApplicationDTO.class);
    }
}
