package com.yeejoin.amos.boot.module.app.biz.service.impl;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.codec.Base64Encoder;
import com.yeejoin.amos.boot.biz.common.dto.JgUseRegistrationManageDto;
import com.yeejoin.amos.boot.module.app.api.dto.CertInfoRequestParam;
import com.yeejoin.amos.boot.module.app.api.exception.AuthException;
import com.yeejoin.amos.boot.module.app.api.mapper.AppCommonMapper;
import com.yeejoin.amos.boot.module.app.biz.strategy.SearchDetailStrategyContext;
import com.yeejoin.amos.boot.module.common.api.crypto.AESUtil;
import com.yeejoin.amos.boot.module.common.api.enums.CertificateStatusEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@Service
public class CertDetailServiceImpl {

    private final AppCommonMapper commonMapper;

    private static final String REG_TYPE_VEHICLE = "车用气瓶登记";

    public CertDetailServiceImpl(AppCommonMapper commonMapper) {
        this.commonMapper = commonMapper;
    }

    public Map<String, Object> getCertInfoForWX(CertInfoRequestParam requestParam) {
        this.setDefaultFieldForOld(requestParam);
        String certOrApplyNo = this.deCodeCertNo(requestParam.getCertNo());
        String version = this.deCodeByAES(requestParam.getVersion());
        String certType = this.deCodeByBase64(requestParam.getCertType());
        JgUseRegistrationManageDto jgUseRegistrationManage = this.checkParam(certOrApplyNo, version);
        return SearchDetailStrategyContext.getHandler(this.getManageType(jgUseRegistrationManage)).handler(jgUseRegistrationManage, certType);
    }

    private String deCodeByBase64(String certType) {
        try {
            return Base64Decoder.decodeStr(certType, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new AuthException("非法的二维码！");
        }
    }

    private void setDefaultFieldForOld(CertInfoRequestParam requestParam) {
        // 兼容老数据,默认版本号为1  aes加密
        if (StringUtils.isBlank(requestParam.getVersion())) {
            requestParam.setVersion(AESUtil.encrypt("1"));
        }
        // 兼容老数据,默认类型为使用登记证，扩展预览字段 base64编码
        if (StringUtils.isBlank(requestParam.getCertType())) {
            requestParam.setCertType(Base64Encoder.encode("useCert", StandardCharsets.UTF_8));
        }
    }

    private JgUseRegistrationManageDto checkParam(String certOrApplyNo, String version) {
        JgUseRegistrationManageDto jgUseRegistrationManage = commonMapper.selectOneCert(certOrApplyNo);
        if (jgUseRegistrationManage == null) {
            throw new AuthException("无此证信息！");
        }
        // 表创建字段时已经给默认值 1 正常不为null 程序健壮处理
        if (jgUseRegistrationManage.getVersion() == null) {
            jgUseRegistrationManage.setVersion(1);
        }
        // 版本号变化后  则扫码为旧证 进行业务提示
        if (!jgUseRegistrationManage.getVersion().toString().equals(version)) {
            throw new AuthException(this.buildErrorInfo(jgUseRegistrationManage));
        }
        // 注销业务后，则提示证已注销
        if (CertificateStatusEnum.YIZHUXIAO.getName().equals(jgUseRegistrationManage.getCertificateStatus())) {
            throw new AuthException("此证已注销！");
        }
        return jgUseRegistrationManage;
    }

    private String buildErrorInfo(JgUseRegistrationManageDto jgUseRegistrationManage) {
        return "由于办理" + jgUseRegistrationManage.getChangeReason() + "业务导致该证注销, 请联系监管单位进行换证！";
    }

    /**
     * aes 解密
     *
     * @param data 被解密字段
     * @return 解密后数据
     */
    private String deCodeByAES(String data) {
        try {
            return AESUtil.decrypt(data);
        } catch (Exception e) {
            throw new AuthException("非法的二维码！");
        }
    }

    private String deCodeCertNo(String certNo) {
        // 老数据兼容支持，原有已经发出的使用登记证及使用标志的二维码仅为applyNo，老数据不进行解密验证
        if (certNo.startsWith("SYDJ") || certNo.startsWith("YZBG")) {
            return certNo;
        }
        try {
            return AESUtil.decrypt(certNo);
        } catch (Exception e) {
            throw new AuthException("非法的二维码！");
        }
    }

    /**
     * 使用策略模式进行，不同类型证详情的业务处理
     *
     * @param jgUseRegistrationManage 证信息
     * @return 管理方式：vehicle-车用气瓶；set-台套类设备；unit-单位办理类设备
     */
    private String getManageType(JgUseRegistrationManageDto jgUseRegistrationManage) {
        // 分3类：单位办理方式[unit](气瓶、压力管道）、台套办理方式[set](7大类,不包含压力管道)、车用气瓶[vehicle](压力容器->气瓶)
        String regType = jgUseRegistrationManage.getRegType();
        if (REG_TYPE_VEHICLE.equals(regType)) {
            return "vehicle";
        }
        return jgUseRegistrationManage.getManageType() == null ? "set" : jgUseRegistrationManage.getManageType();
    }

    public Map<String, Object> getCertInfoByCertNoForWX(CertInfoRequestParam requestParam) {
        JgUseRegistrationManageDto jgUseRegistrationManage = this.searchCertByParam(requestParam.getCertNo());
        return SearchDetailStrategyContext.getHandler(this.getManageType(jgUseRegistrationManage)).handler(jgUseRegistrationManage, "useCert");
    }

    private JgUseRegistrationManageDto searchCertByParam(String certNo) {
        JgUseRegistrationManageDto jgUseRegistrationManage = commonMapper.searchOneCertByParam(certNo);
        if (jgUseRegistrationManage == null) {
            throw new AuthException("无此证信息！");
        }
        return jgUseRegistrationManage;
    }
}
