package com.zt.plat.module.qms.resource.device.service;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.plugins.pagination.Page;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.module.qms.common.service.BusinessFileService;
import com.zt.plat.module.qms.core.constant.DataTypeConstant;
import com.zt.plat.module.qms.resource.device.controller.vo.DeviceInfomationPageReqVO;
import com.zt.plat.module.qms.resource.device.controller.vo.DeviceInfomationRespVO;
import com.zt.plat.module.qms.resource.device.controller.vo.DeviceInfomationSaveReqVO;
import com.zt.plat.module.qms.resource.device.controller.vo.DeviceInfomationWithProductVO;
import com.zt.plat.module.qms.resource.device.dal.dataobject.DeviceInfoWithBizConfigVO;
import com.zt.plat.module.qms.resource.device.dal.dataobject.DeviceInfomationDO;
import com.zt.plat.module.qms.resource.device.dal.dataobject.DeviceProductDO;
import com.zt.plat.module.qms.resource.device.dal.mapper.DeviceInfomationMapper;
import com.zt.plat.module.qms.resource.device.enums.DeviceBizEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import java.util.*;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static com.zt.plat.module.qms.enums.ErrorCodeConstants.DEVICE_INFOMATION_NOT_EXISTS;
import static com.zt.plat.module.qms.enums.ErrorCodeConstants.DEVICE_PRODUCT_NOT_EXISTS;


/**
 * 设备-设备信息 Service 实现类
 *
 * @author 后台管理
 */
@Service
@Validated
public class DeviceInfomationServiceImpl implements DeviceInfomationService {

    @Resource
    private DeviceInfomationMapper deviceInfomationMapper;
    @Resource
    private DeviceProductService deviceProductService;
    @Resource private BusinessFileService businessFileService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<DeviceInfomationRespVO> saveDevice(DeviceInfomationSaveReqVO reqVO) {
        Long productId = reqVO.getProductId();
        String deviceCode = reqVO.getDeviceCode();
        if (productId == null)
            throw exception0(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "请选择所属设备大类！");
        DeviceProductDO productDO = deviceProductService.getDeviceProduct(productId);
        if (productDO == null)
            throw exception(DEVICE_PRODUCT_NOT_EXISTS);
        if (!DataTypeConstant.DATA_TYPE_DATA.equals(productDO.getNodeType()))
            throw exception0(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "您选择的是“分类”，请选择“产品”！");
        DeviceInfomationDO checkData = getByCode(deviceCode);
        if (reqVO.getId() == null) {
            if (checkData != null && !checkData.getId().equals(reqVO.getId()))
                throw exception0(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "管理编号已存在，请重新填写！");
            DeviceInfomationRespVO respVO = this.createDeviceInfomation(reqVO);
            return CommonResult.success(respVO);
        }
        if (checkData != null)
            throw exception0(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "管理编号已存在，请重新填写！");
        reqVO.setDeviceParameter(productDO.getParameter());
        this.updateDeviceInfomation(reqVO);
        return CommonResult.success(BeanUtils.toBean(reqVO, DeviceInfomationRespVO.class));
    }

    @Override
    public CommonResult<DeviceInfomationRespVO> updateDeviceStatus(JSONObject param) {
        Long deviceId = param.getLong("deviceId");
        String bizType = param.getString("bizType");
        Integer switchState = param.getInteger("switchState");
        DeviceInfomationDO deviceDO = this.getDeviceInfomation(deviceId);
        initDeviceStatusByBizType(deviceDO, bizType, switchState);
        this.updateDeviceInfomation(deviceDO);
        return CommonResult.success(BeanUtils.toBean(deviceDO, DeviceInfomationRespVO.class));
    }

    @Override
    public CommonResult<Boolean> checkDeviceUsable(Long id) {
        DeviceInfomationDO deviceDO = this.getDeviceInfomation(id);
        if (ObjectUtils.isEmpty(deviceDO))
            return CommonResult.error(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "设备不存在，请刷新后重试！");
        String deviceStatus = deviceDO.getDeviceStatus();
        if(ObjectUtils.isEmpty(deviceStatus))
            return CommonResult.success(true);
        JSONObject deviceStatusJson = JSON.parseObject(deviceStatus);

        if (!"1".equals(deviceStatusJson.getString(DeviceBizEnum.enable.getCode())))
            return CommonResult.error(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "设备已停用！");
        if ("1".equals(deviceStatusJson.getString(DeviceBizEnum.scrap.getCode())))
            return CommonResult.error(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "设备已报废！");
        if ("1".equals(deviceStatusJson.getString(DeviceBizEnum.borrow.getCode())))
            return CommonResult.error(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "设备已外借！");
        if ("1".equals(deviceStatusJson.getString(DeviceBizEnum.repair.getCode())))
            return CommonResult.error(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "设备在维修中");
        return CommonResult.success(true);
    }

    /*查询需要“某个业务类型”的设备列表*/
    @Override
    public List<DeviceInfoWithBizConfigVO> getListNeedByRule(JSONObject params) {
        return deviceInfomationMapper.getListNeedByRule(params);
    }

    /*
     * 更新设备生命周期状态
     * 传入设备实体、业务类型（停用、外借、维修、降级等）、状态（1-是，其他-否）
     * */
    @Override
//    @Transactional(rollbackFor = Exception.class)
    public CommonResult<DeviceInfomationDO> initDeviceStatusByBizType(DeviceInfomationDO info, String bizType, Integer switchState) {
        String stateStack = info.getStateStack();
        JSONArray arr = new JSONArray();
        if (!ObjectUtils.isEmpty(stateStack))
            arr = JSON.parseArray(stateStack);
//        String state = "-1";
        DeviceBizEnum biz = DeviceBizEnum.getByCode(bizType);
        if (biz == null)
            throw exception0(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "更新设备状态时发生错误，业务类型不存在：" + bizType);
        JSONObject bizJson = DeviceBizEnum.getStateBySwitch(bizType, switchState);
        if(bizJson == null)
            throw exception0(DEVICE_INFOMATION_NOT_EXISTS.getCode(), "更新设备状态时发生错误，业务类型不存在：" + bizType);
        String flag = bizJson.getString("flag");
        boolean updateStateShow = bizJson.getBoolean("updateStateShow");
        String deviceStatus = info.getDeviceStatus();
        JSONObject deviceStatusJson = new JSONObject();
        if(!ObjectUtils.isEmpty(deviceStatus)){
            deviceStatusJson = JSON.parseObject(deviceStatus);
//            Object obj = JSON.parse(deviceStatus);
//            if (obj instanceof JSONObject) {
//                deviceStatusJson = (JSONObject) obj;
//            }else if (obj instanceof String) {
//                // 如果解析出来是 String，说明它是 "{\"A\":\"1\"}" 这种格式
//                // 需要再解析一次
//                String innerJson = (String) obj;
//                deviceStatusJson = JSON.parseObject(innerJson);
//            }
        }
//
        deviceStatusJson.put(bizType, flag);
        info.setDeviceStatus(deviceStatusJson.toJSONString());
//        if (bizType.equals(DeviceBizEnum.accept.getCode())) {
//            info.setAcceptanceFlag(flag);
//        }
//        if (bizType.equals(DeviceBizEnum.repair.getCode())) {
//            info.setRepairFlag(flag);
//        }
//        if (bizType.equals(DeviceBizEnum.demote.getCode())) {
//            info.setDemoteFlag(flag);
//        }
//        if (bizType.equals(DeviceBizEnum.scrap.getCode())) {
//            info.setScrapFlag(flag);
//        }
//        if (bizType.equals(DeviceBizEnum.enable.getCode())) {
//            info.setDisableFlag(flag);
//        }
//        if (bizType.equals(DeviceBizEnum.borrow.getCode())) {
//            info.setLendFlag(flag);
//        }
        //未传入状态，则切换状态

        if(updateStateShow){
            JSONObject json = null;
            int index = -1;
            boolean itemFindFlag = false;
            for (int i = 0; i < arr.size(); i++) {
                index = i;
                JSONObject item = arr.getJSONObject(i);
                if (item.getString("bizType").equals(bizType)) {
                    json = item;
                    itemFindFlag = true;
                    break;
                }
            }
            //如果栈里不存在记录
            if (json == null) {
                //状态为正常，不做处理
                if (!"0".equals(flag)) {
                    //插入记录
                    json = new JSONObject();
                    json.put("bizType", bizType);
                    json.put("state", flag);
                    arr.add(0, json);
                }
            } else {
                //存在记录，移至最前端
                if (itemFindFlag)
                    arr.remove(index);
                if ("1".equals(flag))
                    arr.add(0, json);
            }
            info.setStateStack(arr.toJSONString());
            if (arr.isEmpty()) {
                info.setStateShow("正常");
            } else {
                JSONObject first = arr.getJSONObject(0);
                String firstBiz = first.getString("bizType");
                DeviceBizEnum bizEnum = DeviceBizEnum.getByCode(firstBiz) ;
                info.setStateShow(bizEnum.getDescribe());
            }
        }

        //更新数据
//        LambdaUpdateWrapper<DeviceInfomationDO> updateWrapper = new LambdaUpdateWrapper<>();
//        updateWrapper.eq(DeviceInfomationDO::getId, info.getId());
//        updateWrapper.set(tableField, state);
//        updateWrapper.set(DeviceInfomationDO::getStateShow, info.getStateShow());
//        updateWrapper.set(DeviceInfomationDO::getStateStack, info.getStateStack());
//        deviceInfomationMapper.update(updateWrapper);
        return CommonResult.success(info);
    }

    /*
     * 更新“使用中”状态*/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDeviceInUseFlag(Long deviceId, Integer inUseFlag) {
        String state = (1 == inUseFlag) ? "1" : "0";
        LambdaUpdateWrapper<DeviceInfomationDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(DeviceInfomationDO::getId, deviceId);
        updateWrapper.set(DeviceInfomationDO::getInUseFlag, state);
        deviceInfomationMapper.update(updateWrapper);
    }

    @Override
    public void updateBatch(List<DeviceInfomationDO> updateList) {
        deviceInfomationMapper.updateBatch(updateList);
    }

    @Override
    public DeviceInfomationDO getByCode(String code) {
        LambdaQueryWrapper<DeviceInfomationDO> query = new LambdaQueryWrapper<>();
        query.eq(DeviceInfomationDO::getDeviceCode, code);
        return deviceInfomationMapper.selectOne(query);
    }

    @Override
    public List<DeviceInfomationDO> getListByProductIdList(List<Long> productIds) {
        LambdaQueryWrapper<DeviceInfomationDO> query = new LambdaQueryWrapper<>();
        query.in(DeviceInfomationDO::getProductId, productIds);
        return deviceInfomationMapper.selectList(query);
    }

    @Override
    public List<DeviceInfomationDO> getListByIds(String ids) {
        if (ObjectUtils.isEmpty(ids))
            return Collections.emptyList();
        List<Long> idsList = Arrays.asList(ids.split(",")).stream().map(Long::parseLong).toList();
        return deviceInfomationMapper.selectByIds(idsList);
    }

    @Override
    public List<Long> getIdListByProductIdList(List<Long> productIds) {
        List<DeviceInfomationDO> list = getListByProductIdList(productIds);
        return list.stream().map(DeviceInfomationDO::getId).toList();
    }

    @Override
    public DeviceInfomationRespVO createDeviceInfomation(DeviceInfomationSaveReqVO createReqVO) {
        // 插入
        DeviceInfomationDO deviceInfomation = BeanUtils.toBean(createReqVO, DeviceInfomationDO.class);
        deviceInfomationMapper.insert(deviceInfomation);
        // 返回
        return BeanUtils.toBean(deviceInfomation, DeviceInfomationRespVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DeviceInfomationDO updateDeviceInfomation(DeviceInfomationSaveReqVO updateReqVO) {
        // 校验存在
        validateDeviceInfomationExists(updateReqVO.getId());
        // 更新
        DeviceInfomationDO updateObj = BeanUtils.toBean(updateReqVO, DeviceInfomationDO.class);
        deviceInfomationMapper.updateById(updateObj);
        businessFileService.deleteBusinessFileList(updateReqVO.getDeleteFileIdList());
        return updateObj;
    }

    @Override
    public DeviceInfomationDO updateDeviceInfomation(DeviceInfomationDO entity) {
        deviceInfomationMapper.updateById(entity);
        return entity;
    }

    @Override
    public void deleteDeviceInfomation(Long id) {
        // 校验存在
        validateDeviceInfomationExists(id);
        // 删除
        deviceInfomationMapper.deleteById(id);
    }

    @Override
    public void deleteDeviceInfomationListByIds(List<Long> ids) {
        // 校验存在
        validateDeviceInfomationExists(ids);
        // 删除
        deviceInfomationMapper.deleteByIds(ids);
    }

    private void validateDeviceInfomationExists(List<Long> ids) {
        List<DeviceInfomationDO> list = deviceInfomationMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(DEVICE_INFOMATION_NOT_EXISTS);
        }
    }

    private void validateDeviceInfomationExists(Long id) {
        if (deviceInfomationMapper.selectById(id) == null) {
            throw exception(DEVICE_INFOMATION_NOT_EXISTS);
        }
    }

    @Override
    public DeviceInfomationDO getDeviceInfomation(Long id) {
        return deviceInfomationMapper.selectById(id);
    }

    @Override
    public DeviceInfomationWithProductVO getDeviceWithProduct(Long id) {
        IPage<DeviceInfomationPageReqVO> page = new Page<>(1, 1);
        DeviceInfomationPageReqVO pageReqVO = new DeviceInfomationPageReqVO();
        pageReqVO.setId(id);
        Page<DeviceInfomationWithProductVO> pageList = deviceInfomationMapper.selectPage(page, pageReqVO);
        if(!pageList.getRecords().isEmpty())
            return pageList.getRecords().get(0);
        return null;
    }

    @Override
    public PageResult<DeviceInfomationWithProductVO> getDeviceInfomationPage(DeviceInfomationPageReqVO pageReqVO) {
        IPage<DeviceInfomationPageReqVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        Page<DeviceInfomationWithProductVO> pageList = deviceInfomationMapper.selectPage(page, pageReqVO);
        PageResult<DeviceInfomationWithProductVO> pageResult = new PageResult<>(pageList.getRecords(), pageList.getTotal());
        return pageResult;
    }

}