package com.sunyard.ssp.modules.sysconf.cipherunit.controller;

import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.chsm.model.entity.ParamConf;
import com.sunyard.ssp.common.Result;
import com.sunyard.ssp.common.annotation.AuditControllerLog;
import com.sunyard.ssp.common.exception.SspwebException;
import com.sunyard.ssp.modules.jna.CipherJna;
import com.sunyard.ssp.modules.sysconf.cipherunit.entity.ScCipherMachine;
import com.sunyard.ssp.modules.sysconf.cipherunit.entity.ScCipherMachineVo;
import com.sunyard.ssp.modules.sysconf.cipherunit.enums.RetEnum;
import com.sunyard.ssp.modules.sysconf.cipherunit.service.ScCipherMachineService;
import com.sunyard.ssp.modules.sysconf.cipherunit.utils.IniFileUpdater;
import com.sunyard.ssp.modules.sysconf.paramconf.service.IParamConfService;
import com.sunyard.ssp.utils.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * 密码部件管理控制层
 *
 * @author admin
 */
@Controller
@Slf4j
@Api(description = "关键密码部件管理接口", tags = "关键密码部件管理")
@RequestMapping("/cipherMachine")
public class ScCipherMachineController {
    @Autowired
    private ScCipherMachineService scCipherMachineService;

    @Autowired
    private IParamConfService iParamConfService;

//    @ControllerLog("获取关键密码部件部件")
    @RequestMapping(value = "/query", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "获取关键密码部件部件")
    public Result<ScCipherMachineVo> queryCipherMachine() {
        log.info("get请求 /cipherMachine/query接口");
        ScCipherMachineVo scCipherMachineVo = scCipherMachineService.queryCipherMachine();
        log.info("获取密码部件功能响应结果：{}", scCipherMachineVo);
        return new ResultUtil<ScCipherMachineVo>().setData(scCipherMachineVo);
    }

//    @ControllerLog("添加关键密码部件配置")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @AuditControllerLog(description = "添加关键密码部件配置",operateType = "增加")
    @ResponseBody
    @ApiOperation(value = "添加关键密码部件配置")
    public Result<Object> addCipherMachine(@RequestBody ScCipherMachine scCipherMachine) {
        try {
            ScCipherMachine scCipherMachineVo = scCipherMachineService.addCipherMachine(scCipherMachine);
            IniFileUpdater.updateIniFile(scCipherMachine.getIp(),(String) scCipherMachine.getPort());
            return new ResultUtil<>().setData(scCipherMachineVo);
        } catch (SspwebException e) {
            return new ResultUtil<Object>().setErrorMsg(e.getMsg());
        }
    }
//    @ControllerLog("检测")
    @RequestMapping(value = "/detection", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "检测")
    public Result<Object> detection() {
        int size = 16;
        PointerByReference phDeviceHandle = new PointerByReference();
        PointerByReference phSessionHandle = new PointerByReference();
        int code = RetEnum.SUCCESS.getCode();
        try {

            // 打开设备
            int ret = CipherJna.INSTANCE.SDF_OpenDevice(phDeviceHandle);
            if (ret != code) {
                return new ResultUtil<Object>().setErrorMsg(ret, "打开设备失败，密码模块初始化失败");
            }
            Pointer hDeviceHandle = phDeviceHandle.getValue();
            // 打开会话
            ret = CipherJna.INSTANCE.SDF_OpenSession(hDeviceHandle, phSessionHandle);
            if (ret != code) {
                return new ResultUtil<Object>().setErrorMsg(ret, "打开会话失败，密码模块初始化失败");
            }
            byte[] nakedSign = new byte[size];
            // 生成随机数
            ret = CipherJna.INSTANCE.SDF_GenerateRandom(phSessionHandle.getValue(), 16, nakedSign);
            if (ret != code) {
                return new ResultUtil<Object>().setErrorMsg(ret, "生成随机数失败，密码模块初始化失败");
            }
            // 返回结果
            String result = Hex.encodeHexString(nakedSign);
            log.info("检测功能响应结果：{}", result);
            return new ResultUtil<>().setData(result);
        } catch (SspwebException e) {
            return new ResultUtil<Object>().setErrorMsg(e.getMsg());
        } catch (Throwable e) {
            log.error("检测异常：" + e);
            return new ResultUtil<Object>().setErrorMsg("密码模块初始化失败");
        } finally {
            // 关闭会话
            if (phSessionHandle.getValue() != null) {
                int ret = CipherJna.INSTANCE.SDF_CloseSession(phSessionHandle.getValue());
                if (ret != code) {
                    log.error("关闭会话失败：{}", ret);
                }
            }
            // 关闭设备
            if (phDeviceHandle.getValue() != null) {
                int ret = CipherJna.INSTANCE.SDF_CloseDevice(phDeviceHandle.getValue());
                if (ret != code) {
                    log.error("关闭设备失败：{}", ret);
                }
            }
        }
    }

//    @ControllerLog("密码模块初始化")
    @RequestMapping(value = "/init", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "密码模块初始化")
    public Result<Object> init() {
        int size = 16;
        PointerByReference phDeviceHandle = new PointerByReference();
        PointerByReference phSessionHandle = new PointerByReference();
        int code = RetEnum.SUCCESS.getCode();
        try {

//            // 打开设备
//            int ret = CipherJna.INSTANCE.SDF_OpenDevice(phDeviceHandle);
//            if (ret != code) {
//                return new ResultUtil<Object>().setErrorMsg(ret, "打开设备失败");
//            }
//            Pointer hDeviceHandle = phDeviceHandle.getValue();
//            // 打开会话
//            ret = CipherJna.INSTANCE.SDF_OpenSession(hDeviceHandle, phSessionHandle);
//            if (ret != code) {
//                return new ResultUtil<Object>().setErrorMsg(ret, "打开会话失败");
//            }
//            byte[] nakedSign = new byte[size];
//            // 生成随机数
//            ret = CipherJna.INSTANCE.SDF_GenerateRandom(phSessionHandle.getValue(), 16, nakedSign);
//            if (ret != code) {
//                return new ResultUtil<Object>().setErrorMsg(ret, "生成随机数失败");
//            }
//            // 返回结果
//            String result = Util.bytes2HexString(nakedSign);
//            log.info("检测功能响应结果：{}", result);
            ParamConf paramConf = iParamConfService.selectByKey("initStatus");
            if (paramConf != null) {
                paramConf.setValue("1");
                iParamConfService.updateById(paramConf);
            }
            return new ResultUtil<>().setSuccessMsg("初始化成功");
        } catch (SspwebException e) {
            return new ResultUtil<Object>().setErrorMsg(e.getMsg());
        } catch (Throwable e) {
            log.error("检测异常：" + e);
            return new ResultUtil<Object>().setErrorMsg("检测失败");
        } finally {
            // 关闭会话
            if (phSessionHandle.getValue() != null) {
                int ret = CipherJna.INSTANCE.SDF_CloseSession(phSessionHandle.getValue());
                if (ret != code) {
                    log.error("关闭会话失败：{}", ret);
                }
            }
            // 关闭设备
            if (phDeviceHandle.getValue() != null) {
                int ret = CipherJna.INSTANCE.SDF_CloseDevice(phDeviceHandle.getValue());
                if (ret != code) {
                    log.error("关闭设备失败：{}", ret);
                }
            }
        }
    }

//    @ControllerLog("密码模块初始化状态获取")
    @RequestMapping(value = "/init/status", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "密码模块初始化状态获取")
    public Result<Object> initStatus() {
        ParamConf paramConf = iParamConfService.selectByKey("initStatus");
        if (paramConf != null) {
            return new ResultUtil<>().setData(paramConf.getValue());
        } else {
            return new ResultUtil<>().setErrorMsg("获取初始化状态失败");
        }
    }


//    @ControllerLog("编辑关键密码部件配置")
    @RequestMapping(value = "/edit", method = RequestMethod.PUT)
    @AuditControllerLog(description = "编辑关键密码部件配置",operateType = "修改")
    @ResponseBody
    @ApiOperation(value = "编辑关键密码部件配置")
    public Result<Object> editCipherMachine(@RequestBody ScCipherMachine scCipherMachine) {
        try {
            log.info("put请求 /cipherMachine/edit 请求参数：{}", scCipherMachine);
            ScCipherMachine scCipherMachineVo = scCipherMachineService.editCipherMachine(scCipherMachine);
            log.info("编辑关键密码部件功能响应结果：{}", scCipherMachineVo);
            IniFileUpdater.updateIniFile(scCipherMachine.getIp(),(String) scCipherMachine.getPort());
            return new ResultUtil<>().setData(scCipherMachineVo);
        } catch (SspwebException e) {
            return new ResultUtil<Object>().setErrorMsg(e.getMsg());
        }
    }
//    @ControllerLog("删除关键密码部件配置")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
    @AuditControllerLog(description = "删除关键密码部件配置",operateType = "删除")
    @ResponseBody
    @ApiOperation(value = "删除关键密码部件配置")
    public Result<Object> deleteCipherMachine(@PathVariable("id") Long id) {
        try {
            log.info("delete请求 /cipherMachine/delete 请求参数：{}", id);
            scCipherMachineService.deleteCipherMachine(id);
            return new ResultUtil<>().setData(null);
        } catch (SspwebException e) {
            return new ResultUtil<Object>().setErrorMsg(e.getMsg());
        }
    }
}
