package com.zd.chemical.controller;

import com.zd.chemical.domain.*;
import com.zd.chemical.domain.vo.*;
import com.zd.chemical.service.*;
import com.zd.common.core.domain.R;
import com.zd.common.core.enums.LockTypeEnum;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.DateUtils;
import com.zd.common.core.utils.SecurityUtils;
import com.zd.common.core.web.controller.BaseController;
import com.zd.common.core.web.page.TableDataInfo;
import com.zd.common.log.annotation.Log;
import com.zd.common.log.enums.BusinessType;
import com.zd.common.security.service.TokenService;
import com.zd.system.api.laboratory.CabinetV2Lock;
import com.zd.system.api.model.LoginUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;

/**
 * 化学品智能终端Controller
 */
@RestController
@RequestMapping("/api")
@Api(tags = {"化学品智能终端"})
public class HxpAIOController extends BaseController {

    /**
     * routes:
     *         # 认证中心
     *         - id: zd-auth
     *             - Path=/auth/**
     *         # 代码生成
     *         - id: zd-gen
     *             - Path=/code/**
     *         # 定时任务
     *         - id: zd-job
     *             - Path=/schedule/**
     *         # 系统模块
     *         - id: zd-system
     *             - Path=/system/**
     *         # 文件服务
     *         - id: zd-file
     *             - Path=/file/**
     *         # 实验室服务
     *         - id: zd-laboratory
     *             - Path=/laboratory/**
     *         # 考试服务
     *         - id: zd-exam
     *             - Path=/exam/**
     *         # 化学品
     *         - id: zd-chemical
     *             - Path=/chemical/**
     *         # 小程序
     *         - id: zd-app
     *             - Path=/app/**
     *         # 人脸识别
     *         - id: zd-face
     *             - Path=/face/**
     *         # 小程序
     *         - id: zd-camera
     *             - Path=/camera/**
     *         # 语音报警
     *         - id: zd-alarm
     *             - Path=/alarm/**
     *         # ip喇叭
     *         - id: zd-speaker
     *             - Path=/speak/**
     */

    private static DateFormat sdf = new SimpleDateFormat("yyMMddssSSS");

    @Autowired
    private TokenService tokenService;
    @Autowired
    private IHxpSmartTerminalService hxpSmartTerminalService;
    @Autowired
    private IHxpCabinetService hxpCabinetService;
    @Autowired
    private IHxpChemicalJoinCabinetService hxpCabinetJoinCabinetService;
    @Autowired
    private IHxpStockService hxpStockService;
    @Autowired
    private IHxpUserecordService hxpUserecordService;
    @Autowired
    private IHxpAlarmRecordService hxpAlarmRecordService;

    /**-------------------------------------BASE 说明---------------------------------------
     * @return*/

    /*
     * 1.获取功能配置基本信息和logo: /system/logo/config/getLogoInfo (无 token 验证，GET)
     * 2.刷卡登录，退出，自动退出功能 - 同学习一体机一致（登录需要machineCode 传参 设备编号）
     */

    // D:\project\lab2.0\lab-distributed-java-2.0\zd-modules\zd-chemical\src\
    // chemical     化学品

    private boolean getCabinetLock(){
        LoginUser user = tokenService.getLoginUser();
        return user.isCabinetLock();
    }

    private String getTerminalNum(){
        LoginUser user = tokenService.getLoginUser();
        if(user == null || StringUtils.isBlank(user.getMachineCode())){
            throw new ServiceException("未获取到设备编号，无效操作！");
        }
        return user.getMachineCode();
    }

    private Long getSubIdByTerminalNum(){
        Long subId = hxpSmartTerminalService.selectSubIdByTerminalNum(getTerminalNum());
        if(subId == null){
            throw new ServiceException("设备未匹配到实验室，请确认设备信息后重新登录！");
        }
        return subId;
    }

    private Long getSubIdByTerminalNum(String machineCode){

        machineCode = StringUtils.isBlank(machineCode) ? getTerminalNum():machineCode;

        Long subId = hxpSmartTerminalService.selectSubIdByTerminalNum(machineCode);
        if(subId == null){
            throw new ServiceException("设备未匹配到实验室，请确认设备信息后重新登录！");
        }
        return subId;
    }

    public static String genTagCode(){
        String tagCode = sdf.format(DateUtils.getNowDate());
        return tagCode.substring(0, tagCode.length());
    }

    /**
     *
     * 判断当前登录人是否管理员
     */
    @PostMapping("/authValidation")
    @ApiOperation(value = "判断当前登录人是否管理员")
    public R<Boolean> selectIsAdminOrSafeUser() {
        return R.ok(hxpUserecordService.selectIsAdminOrSafeUser(getSubIdByTerminalNum(), SecurityUtils.getUserId()));
    }

    /**
     *
     * 终端登录查询实验室信息
     */
    @PostMapping("/querySubInfo")
    @ApiOperation(value = "终端登录查询实验室信息")
    public R<AioSubInfoVo> querySubInfo() {
        return R.ok(hxpCabinetService.querySubInfo(getSubIdByTerminalNum()));
    }

    /**--------------------------------------领用化学品----------------------------------------*/

    /**
     *
     * 双人验证 刷卡识别权限身份
     */
    @PostMapping("/userValidation")
    @ApiOperation(value = "双人验证 刷卡识别身份权限")
    public R<AioUserValidationVo> userValidation(@RequestBody @Valid AioUserValidationVo userValidationVo) {
        if(StringUtils.isBlank(userValidationVo.getCardNum())){
            return R.fail("验证失败：卡号不能为空！");
        }
        userValidationVo.setSubId(getSubIdByTerminalNum());
        userValidationVo = hxpUserecordService.userValidation(userValidationVo);
        return R.ok(userValidationVo);
    }

    /**
     * 领用化学品
     * 同一个化学品领用状态下只能出现一条数据，就是说未归还的前提下，下一个人是无法领用的
     */
    @PostMapping("/addUserecord")
    @ApiOperation(value = "领用化学品")
    public R<HxpUserecord> addUserecord(@RequestBody @Valid HxpUserecord hxpUserecord) {
        hxpUserecord = hxpUserecordService.insertHxpUserecord(hxpUserecord);
        return R.ok(hxpUserecord);
    }

    /**---------------------------------------归还化学品---------------------------------------*/

    /**
     * 归还时查询已领用化学品
     */
    @PostMapping("/queryByUserecord")
    @ApiOperation(value = "归还时查询已领用化学品")
    public R<Object> queryByUserecord(@RequestBody HxpStock hxpStock) {
        if(hxpStock.getId() == null && StringUtils.isBlank(hxpStock.getTagCode())){
            return R.fail("查询失败，卡号不能为空！");
        }
        hxpStock.setStatus(1);
        hxpStock.setSubId(getSubIdByTerminalNum());
        hxpStock.setScanCode(hxpStock.getTagCode());
        hxpStock.setTagCode(null);
        List<HxpStock> list = hxpStockService.selectHxpStockList(hxpStock);
        // 识别结果应该只能有一条
        if(list.size() > 0){
            hxpStock = list.get(0);
            HxpUserecord hxpUserecord = new HxpUserecord();
            hxpUserecord.setUseStatus(1);
            hxpUserecord.setStockId(hxpStock.getId());
            hxpUserecord.setUserId(SecurityUtils.getUserIdEx());
            List<HxpUserecord> userecordList = hxpUserecordService.selectHxpUserecordList(hxpUserecord);
            if(userecordList.size() == 0){
                return R.fail("您当前未领用该化学品，不用归还！");
            }else if(userecordList.size() > 1){
                return R.fail("查询失败：领用数据【" + hxpStock.getScanCode() + "】，请联系管理员！");
            }
            hxpStock.setHxpUserecord(userecordList.get(0));

        }else {
            return R.fail("当前化学品已过期或不存在！");
        }
        return R.ok(hxpStock);
    }

    /**
     * 归还化学品
     */
    @PostMapping("/updateUserecord")
    @ApiOperation(value = "归还化学品")
    public R<HxpUserecord> updateUserecord(@RequestBody HxpUserecord hxpUserecord) {
        if(hxpUserecord.getId() == null){
            return R.fail("参数异常，ID不能为空！");
        }
        if(hxpUserecord.getReturnType() == null){
            return R.fail("归还方式不能为空！");
        }
        if(hxpUserecord.getReturnStockNum() == null){
            return R.fail("称重重量不能为空！");
        }

        hxpUserecord = hxpUserecordService.updateHxpUserecord(hxpUserecord);
        return R.ok(hxpUserecord);
    }

    /**----------------------------------------使用记录--------------------------------------*/
    /**
     * 查询使用记录
     */
    @PostMapping("/queryRecordList")
    @ApiOperation(value = "查询使用记录")
    public TableDataInfo<List<AioUserecordVo>> queryRecordList(@RequestBody AioUserecordVo aioUserecordVo) {
        aioUserecordVo.setSubId(getSubIdByTerminalNum());
        aioUserecordVo.setUserId(SecurityUtils.getUserId());
        startPage();
        List<AioUserecordVo> list = hxpUserecordService.queryRecordList(aioUserecordVo);
        return getDataTable(list);
    }


    /**----------------------------------------报警台账--------------------------------------*/
    /**
     * 查询报警记录列表
     */
    @PostMapping("/queryAlarmRecordList")
    @ApiOperation(value = "查询报警记录列表")
    public TableDataInfo<List<AioAlarmRecordVo>> queryAlarmRecordList(@RequestBody AioAlarmRecordVo aioAlarmRecordVo) {
        aioAlarmRecordVo.setSubId(getSubIdByTerminalNum());
        startPage();
        List<AioAlarmRecordVo> list = hxpAlarmRecordService.queryAlarmRecordList(aioAlarmRecordVo);
        return getDataTable(list);
    }

    /**
     * 查询报警记录详情
     */
    @GetMapping("/queryAlarmRecordDetail")
    @ApiOperation(value = "查询报警记录详情")
    public R<AioAlarmRecordVo> queryAlarmRecordDetail(@RequestParam("id") Long id) {
        return R.ok(hxpAlarmRecordService.queryAlarmRecordDetail(id));
    }

    /**
     * 检测类型报警记录手动处理
     */
    @PostMapping("/updateAlarmRecord")
    @ApiOperation(value = "检测类型报警记录手动处理")
    public R<List<HxpCabinetVo>> updateAlarmRecord(@RequestBody HxpAlarmRecord hxpAlarmRecord) {
        if(hxpAlarmRecord.getId() == null || hxpAlarmRecord.getHandlingStatus() == null){
            return R.fail("参数无效，ID不能为空！");
        }
        hxpAlarmRecordService.updateHxpAlarmRecord(hxpAlarmRecord);
        return R.ok();
    }


    /**----------------------------------------化学品入库--------------------------------------*/

    /**
     * 查询实验室机柜列表
     */
    @PostMapping("/queryCabinetList")
    @ApiOperation(value = "查询实验室机柜列表")
    public R<List<HxpCabinetVo>> queryCabinetList(@RequestBody HxpCabinetSearch hxpCabinetSearch) {
        // 当前实验室机柜
        hxpCabinetSearch.setSubId(getSubIdByTerminalNum());
        List<HxpCabinetVo> list = hxpCabinetService.selectHxpCabinetList(hxpCabinetSearch);
        return R.ok(list);
    }

    /**
     * 入库查询化学品配置信息
     */
    @PostMapping("/queryChemicalList")
    @ApiOperation(value = "入库查询化学品配置信息")
    public TableDataInfo<List<AioChemicalVo>> queryChemicalList(@RequestBody AioChemicalVo aioChemicalVo) {
        // 当前实验室机柜
        aioChemicalVo.setSubId(getSubIdByTerminalNum());
        startPage();
        List<AioChemicalVo> list = hxpCabinetJoinCabinetService.selectChemicalVoList(aioChemicalVo);
        return getDataTable(list);
    }

    /**
     * 化学品入库
     */
    @PostMapping("/addStock")
    @ApiOperation(value = "化学品入库")
    public R<HxpStock> addStock(@RequestBody @Valid HxpStock hxpStock) {
        // 化学品入库
        return R.ok(hxpStockService.insertHxpStock(hxpStock));
    }

    /**----------------------------------------化学品出库--------------------------------------*/

    /**
     * 通过识别卡号或者二维码扫码查询已入库化学品
     */
    @PostMapping("/queryByTagCode")
    @ApiOperation(value = "通过识别卡号或者二维码扫码查询已入库化学品")
    public R<Object> queryByTagCode(@RequestBody HxpStock hxpStock) {
        if(StringUtils.isBlank(hxpStock.getTagCode())){
            return R.fail("查询失败，卡号不能为空！");
        }
        int qType = hxpStock.getqType();
        // 终端传参数据有问题，暂临时后端处理
//        hxpStock.setTagCode(hxpStock.getTagCode().replaceAll("%00", "").trim());

        if(qType != 2 && qType != 5){
            //hxpStock.setStatus(1);
            hxpStock.setSubId(getSubIdByTerminalNum(hxpStock.getMachineCode()));
        }
//        if(qType == 3){
//            hxpStock.setStatus(null);
//        }
        logger.info("queryByTagCode 查询参数：" + hxpStock.getTagCode()+ ", 实验室ID：" + hxpStock.getSubId() + ", qType: " + hxpStock.getqType());

        hxpStock.setScanCode(hxpStock.getTagCode());
        hxpStock.setTagCode(null);
        List<HxpStock> list = hxpStockService.selectHxpStockList(hxpStock);
        // 识别结果应该只能有一条
        if(list.size() == 0){
            logger.info("入参校验qType000000000：" + qType);
            if(qType != 0 && qType != 2){
                return R.fail("未查询到数据：查无数据或已出库！");
            }

            hxpStock = null;
        }else if(list.size() == 1){
            logger.info("入参校验qType1111111：" + qType);
            hxpStock = list.get(0);

            if(hxpStock.getStatus() == 4){
                return R.fail("操作失败：该化学品已过期！");
            }

            if((hxpStock.getStatus() == 2 ||  hxpStock.getStatus() == 3)){
                return R.fail("操作失败：该化学品已出库！");
            }

            if(qType > 0){
                // qType 1-领用化学品 2-化学品入库 3-化学品出库 4-归还化学品 5-RFID标签更换 6-查询化学品
                HxpUserecord hxpUserecord = new HxpUserecord();
                hxpUserecord.setUseStatus(1);
                hxpUserecord.setStockId(hxpStock.getId());
                List<HxpUserecord> userecordList;
                switch (qType) {
                    case 1:
                    case 3:
                        // 化学品出库
                        userecordList = hxpUserecordService.selectHxpUserecordList(hxpUserecord);
                        if(userecordList.size() > 0){
                            if(qType == 1){
                                // 领用化学品
                                return R.fail("该化学品领用中，还未归还！");
                            }
                            return R.fail("化学品领用中，请先完成归还后再操作出库。");
                        }
                        break;
                    case 2:
                    case 5:
                        // RFID标签更换
                        // 化学品入库
                        return R.fail("该标签已绑定，请扫描新的RFID标签。");
                    case 4:
                        // 归还化学品
                        hxpUserecord.setUserId(SecurityUtils.getUserIdEx());
                        userecordList = hxpUserecordService.selectHxpUserecordList(hxpUserecord);
                        if(userecordList.size() == 0){
                            return R.fail("您当前未领用该化学品，不用归还！");
                        }
                        break;
                    case 6:
                        // 查询化学品
                }
            }
        }else {
            return R.fail("数据异常，请联系管理员！");
        }
        return R.ok(hxpStock);
    }

    /**
     * 化学品出库
     */
    @PostMapping("/outStock")
    @ApiOperation(value = "化学品出库")
    public R<Object> outStock(@RequestBody HxpStock hxpStock) {
        if(hxpStock.getId() == null || !(hxpStock.getStatus() == 2 || hxpStock.getStatus() == 3)){
            return R.fail("出库失败，参数异常！");
        }
        hxpStockService.outStock(hxpStock);
        return R.ok();
    }

    /**----------------------------------------标签管理--------------------------------------*/
    /**
     * 标签管理列表查询
     */
    @PostMapping("/queryTagByStock")
    @ApiOperation(value = "标签列表查询: 此接口不调用", notes =
            "1. queryChemicalList 获取标签列表，" +
            "2. queryChemicalByStock （joinId）获取标签已入库标签列表")
    public R queryTagByStock(@RequestBody HxpStock hxpStock) {

        return R.ok();
    }

    /**
     * RFID 标签更换
     */
    @PostMapping("/updateStock")
    @ApiOperation(value = "RFID 标签更换")
    public R<Object> updateStock(@RequestBody HxpStock hxpStock) {
        if(hxpStock.getId() == null || StringUtils.isBlank(hxpStock.getRfidCode())){
            return R.fail("操作失败，参数异常！");
        }

        hxpStockService.updateHxpStock(hxpStock);
        return R.ok();
    }
    // 二维码信息打印 数据接口均已返回

    /**--------------------------------------查询化学品----------------------------------------*/

    /**
     * 查询化学品
     */
    @PostMapping("/queryChemicalByStock")
    @ApiOperation(value = "查询化学品")
    public TableDataInfo<List<HxpStock>> queryChemicalByStock(@RequestBody HxpStock hxpStock) {
        hxpStock.setSubId(getSubIdByTerminalNum());
        hxpStock.setStatus(1);
        startPage();
        List<HxpStock> list = hxpStockService.selectHxpStockList(hxpStock);
        return getDataTable(list);
    }

    /**--------------------------------------柜锁相关接口----------------------------------------*/

    /**
     * 查询机柜柜锁列表
     */
    @PostMapping("/queryCabinetLockList")
    @ApiOperation(value = "查询机柜柜锁列表")
    public R<List<AioCabinetLockVo>> queryCabinetLockList(@RequestBody AioCabinetLockVo aioCabinetLockVo) {
        aioCabinetLockVo.setSubId(getSubIdByTerminalNum());
        aioCabinetLockVo.setCabinetLock(getCabinetLock());
        List<AioCabinetLockVo> list = hxpCabinetService.queryCabinetLockList(aioCabinetLockVo);
        return R.ok(list);
    }

    /**
     * 柜锁开锁
     */
    @PostMapping("/openLock")
    @Log(title = "柜锁开锁", businessType = BusinessType.INSERT)
    @ApiOperation(value = "柜锁开锁")
    public R<CabinetV2Lock> openLock(@RequestBody @Valid AioCabinetLockVo aioCabinetLockVo) {
        if(LockTypeEnum.SYSTEM == aioCabinetLockVo.getLockType()){
            if(aioCabinetLockVo.getLockId() == null){
                return R.fail("柜锁参数不能为空！");
            }
        }else if(aioCabinetLockVo.getJoinId() == null){
            return R.fail("柜锁参数不能为空 !");
        }
        aioCabinetLockVo.setSubId(getSubIdByTerminalNum());
        CabinetV2Lock cabinetV2Lock = hxpCabinetService.openLock(aioCabinetLockVo);
        if(cabinetV2Lock.isSuccess()){
            return R.ok(cabinetV2Lock);
        }else {
            return R.fail(cabinetV2Lock, cabinetV2Lock.getMsg());
        }
    }

    /**
     * 柜锁关锁
     */
    @PostMapping("/closeLock")
    @Log(title = "柜锁关锁", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "柜锁关锁")
    public R<CabinetV2Lock> closeLock(@RequestBody @Valid AioCabinetLockVo aioCabinetLockVo) {
        if(LockTypeEnum.SYSTEM == aioCabinetLockVo.getLockType()){
            if(aioCabinetLockVo.getLockId() == null){
                return R.fail("柜锁参数不能为空！");
            }
        }else if(aioCabinetLockVo.getJoinId() == null){
            return R.fail("柜锁参数不能为空 !");
        }

        if(aioCabinetLockVo.getLockLogId() == null){
            return R.fail("开锁ID不能为空 !");
        }

        aioCabinetLockVo.setSubId(getSubIdByTerminalNum());
        CabinetV2Lock cabinetV2Lock = hxpCabinetService.closeLock(aioCabinetLockVo);
        if(cabinetV2Lock.isSuccess()){
            return R.ok(cabinetV2Lock);
        }else {
            return R.fail(cabinetV2Lock, cabinetV2Lock.getMsg());
        }
    }

    /**--------------------------------------人脸验证----------------------------------------*/

    /**
     * 人脸身份验证
     */
    @PostMapping("/faceAuth")
    @ApiOperation(value = "人脸身份验证")
    public R<AioUserValidationVo> faceAuth(@RequestBody AioSubInfoVo aioSubInfoVo) {
        aioSubInfoVo.setSubId(getSubIdByTerminalNum());
        return R.ok(hxpUserecordService.faceAuth(aioSubInfoVo));
    }
}
