package com.njcn.gather.tool.active.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.RSAUtil;
import com.njcn.gather.tool.active.config.ActivateProperties;
import com.njcn.gather.tool.active.service.ActivateService;
import com.njcn.gather.tool.active.vo.ActivationCodePlaintext;
import com.njcn.gather.tool.active.vo.ActivationModule;
import com.njcn.gather.tool.active.vo.ApplicationCodePlaintext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

@EnableConfigurationProperties(ActivateProperties.class)
@RequiredArgsConstructor
@Slf4j
@Service
public class ActivateServiceImpl implements ActivateService {

    private final ActivateProperties props;

    @Override
    public String generateApplicationCode() {
        // 获取当前设备MAC地址
        String macAddress = NetUtil.getLocalMacAddress();
        log.debug("当前设备MAC地址：{}", macAddress);
        ApplicationCodePlaintext data = new ApplicationCodePlaintext();
        data.setMacAddress(macAddress);
        String plaintext = JSONUtil.toJsonStr(data);
        // RSA 加密
        try {
            return RSAUtil.encrypt(plaintext, RSAUtil.stringToPublicKey(props.getPublicKey()));
        } catch (Exception e) {
            log.error("申请码加密失败", e);
            throw new BusinessException(CommonResponseEnum.FAIL, "申请码生成失败");
        }
    }

    @Override
    public ActivationCodePlaintext verifyActivationCode(String activationCode) {
        String plaintext;
        try {
            plaintext = RSAUtil.decrypt(activationCode, RSAUtil.stringToPrivateKey(props.getPrivateKey()));
        } catch (Exception e) {
            log.error("授权码解密失败", e);
            throw new BusinessException(CommonResponseEnum.FAIL, "无效的激活码");
        }
        log.info("新授权码解密：{}", JSONUtil.toJsonStr(plaintext));
        ActivationCodePlaintext activationCodePlaintext = JSONUtil.toBean(plaintext, ActivationCodePlaintext.class);
        String macAddress = NetUtil.getLocalMacAddress();
        if (!StrUtil.equals(activationCodePlaintext.getMacAddress(), macAddress)) {
            log.error("mac地址不匹配");
            throw new BusinessException(CommonResponseEnum.FAIL, "无效的激活码");
        }
        return addOrUpdateLicenseFile(activationCodePlaintext, activationCode);
    }

    @Override
    public ActivationCodePlaintext readLicenseFile() {
        String licenseFilePath = props.getLicenseFilePath();
        log.info("读取授权文件，{}", licenseFilePath);
        if (FileUtil.exist(licenseFilePath)) {
            String content = FileUtil.readUtf8String(licenseFilePath);
            String plaintext;
            try {
                plaintext = RSAUtil.decrypt(content, RSAUtil.stringToPrivateKey(props.getPrivateKey()));
            } catch (Exception e) {
                log.error("授权文件内容解密失败", e);
                throw new BusinessException(CommonResponseEnum.FAIL, "许可信息读取失败");
            }
            return JSONUtil.toBean(plaintext, ActivationCodePlaintext.class);
        }
        return null;
    }

    @Override
    public String generateActivationCode(String applicationCode, ActivationCodePlaintext activationCodePlaintext) {
        // RSA 解密
        String plaintext;
        try {
            plaintext = RSAUtil.decrypt(applicationCode, RSAUtil.stringToPrivateKey(props.getPrivateKey()));
        } catch (Exception e) {
            log.error("申请码解密失败", e);
            throw new BusinessException(CommonResponseEnum.FAIL, "无效的申请码");
        }
        ApplicationCodePlaintext applicationCodePlaintext = JSONUtil.toBean(plaintext, ApplicationCodePlaintext.class);
        if (applicationCodePlaintext == null) {
            log.error("申请码内容为空");
            throw new BusinessException(CommonResponseEnum.FAIL, "无效的申请码");
        }
        String macAddress = applicationCodePlaintext.getMacAddress();
        if (StrUtil.isBlank(macAddress)) {
            log.error("mac地址为空");
            throw new BusinessException(CommonResponseEnum.FAIL, "无效的申请码");
        }
        // 激活码明文
        activationCodePlaintext.setMacAddress(applicationCodePlaintext.getMacAddress());
        // RSA 加密
        String jsonStr = JSONUtil.toJsonStr(activationCodePlaintext);
        log.info("生成激活码明文：{}", jsonStr);
        try {
            return RSAUtil.encrypt(jsonStr, RSAUtil.stringToPublicKey(props.getPublicKey()));
        } catch (Exception e) {
            log.error("生成激活码失败", e);
            throw new BusinessException(CommonResponseEnum.FAIL, "生成激活码失败");
        }
    }

    /**
     * 添加或更新授权文件
     *
     * @param newActivationCodePlaintext 新授权码明文
     * @param activationCode             授权码
     * @return 最新授权码明文
     */
    private ActivationCodePlaintext addOrUpdateLicenseFile(ActivationCodePlaintext newActivationCodePlaintext, String activationCode) {

        log.info("新授权码明文：{}", JSONUtil.toJsonStr(newActivationCodePlaintext));
        ActivationModule newContrast = newActivationCodePlaintext.getContrast();
        ActivationModule newDigital = newActivationCodePlaintext.getDigital();
        ActivationModule newSimulate = newActivationCodePlaintext.getSimulate();

        String licenseFilePath = props.getLicenseFilePath();
        log.info("授权文件路径：{}", licenseFilePath);
        ActivationCodePlaintext oldActivationCodePlaintext = this.readLicenseFile();
        if (oldActivationCodePlaintext == null) {
            // 如果文件不存在，创建新文件
            FileUtil.touch(licenseFilePath);
            // 写入授权文件
            FileUtil.writeUtf8String(activationCode, licenseFilePath);
            return newActivationCodePlaintext;
        } else {
            log.info("旧授权码明文：{}", JSONUtil.toJsonStr(oldActivationCodePlaintext));
            oldActivationCodePlaintext.setMacAddress(newActivationCodePlaintext.getMacAddress());
            if (newContrast != null && newContrast.isPermanently()) {
                oldActivationCodePlaintext.setContrast(newContrast);
            }
            if (newDigital != null && newDigital.isPermanently()) {
                oldActivationCodePlaintext.setDigital(newDigital);
            }
            if (newSimulate != null && newSimulate.isPermanently()) {
                oldActivationCodePlaintext.setSimulate(newSimulate);
            }
            log.info("最新授权码明文：{}", JSONUtil.toJsonStr(oldActivationCodePlaintext));
            String updateContent;
            // 重新加密
            try {
                updateContent = RSAUtil.encrypt(JSONUtil.toJsonStr(oldActivationCodePlaintext), RSAUtil.stringToPublicKey(props.getPublicKey()));
            } catch (Exception e) {
                log.error("授权文件内容加密失败", e);
                throw new BusinessException(CommonResponseEnum.FAIL, "激活失败，请联系管理员");
            }
            FileUtil.writeUtf8String(updateContent, licenseFilePath);
            return oldActivationCodePlaintext;
        }
    }

}
