package org.security.trans.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import org.security.common.Constant;
import org.security.flow.core.constant.ProcessConstant;
import org.security.flow.core.entity.BladeFlow;
import org.security.flow.core.entity.BladeFlowDef;
import org.security.flow.core.feign.IFlowClient;
import org.security.flow.core.utils.FlowUtil;
import org.security.system.feign.ISysClient;
import org.security.trans.app.dto.AppDeviceCheckDTO;
import org.security.trans.app.dto.AppDeviceDTO;
import org.security.trans.app.service.IAppDeviceService;
import org.security.trans.app.vo.AppDeviceCheckItemVO;
import org.security.trans.app.vo.AppDeviceVO;
import org.security.ht.entity.basic.Device;
import org.security.trans.basic.service.IDepartmentService;
import org.security.trans.basic.service.IDeviceService;
import org.security.trans.common.service.IFileService;
import org.security.trans.dailyDuties.entity.DeviceInspection;
import org.security.trans.dailyDuties.entity.DeviceInspectionLine;
import org.security.trans.dailyDuties.service.IDeviceInspectionLineService;
import org.security.trans.dailyDuties.service.IDeviceInspectionService;
import org.security.trans.settings.service.IDeviceCategorySettingsService;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Create by wzf
 * @date 2022/4/28 11:27
 */
@AllArgsConstructor
@Service
public class AppDeviceServiceImpl implements IAppDeviceService {
	private final IDepartmentService departmentService;
	private final IDeviceService deviceService;
	private final IDeviceCategorySettingsService deviceCategorySettingsService;
	private final IDeviceInspectionService deviceInspectionService;
	private final IDeviceInspectionLineService deviceInspectionLineService;
	private final IFileService fileService;
	private final IFlowClient flowClient;
	private final ISysClient sysClient;


	@Override
	public AppDeviceVO getDetail(String id) {
		//获取待检设备的设备id
		DeviceInspection deviceInspection = deviceInspectionService.getOne(new QueryWrapper<DeviceInspection>().lambda()
			.eq(Func.isNotBlank(id), DeviceInspection::getId, id)
			.and(item -> item.eq(DeviceInspection::getStatus, Constant.DEVICE_STATE_INSPECTION)
				.or().eq(DeviceInspection::getStatus, Constant.DEVICE_STATE_OVERTIME_INSPECTION)
				.or().eq(DeviceInspection::getState,Constant.HANDIN_STATE_REFUSE)
			.or().eq(DeviceInspection::getState,ProcessConstant.CANCEL_STATE)));
		//获取设备信息
		AppDeviceVO deviceVO = getAppDeviceDetail(deviceInspection);
		deviceVO.setState(Constant.DEVICE_STATE_INSPECTION.equals(deviceInspection.getStatus()) ? "待检查" : "超期未检查");
		return deviceVO;
	}

	/**
	 * 获取设备详情
	 */
	private AppDeviceVO getAppDeviceDetail(DeviceInspection deviceInspection) {
		Device device = deviceService.getById(deviceInspection.getDeviceId());
		AppDeviceVO deviceVO = Func.copy(device, AppDeviceVO.class);
		deviceVO.setDepName(departmentService.getById(device.getDepId()).getFullName());
		deviceVO.setTypeName(deviceCategorySettingsService.getById(device.getTypeId()).getName());
		return deviceVO;
	}


	@Override
	public List<AppDeviceCheckItemVO> getDeviceItemDetail(String id,String type) {
		//设备检查待办明细数据
		List<DeviceInspectionLine> deviceInspectionLineList = new ArrayList<>();
		if ("1".equals(type)){
			deviceInspectionLineList = deviceInspectionLineService.list(new QueryWrapper<DeviceInspectionLine>().lambda()
				.eq(Func.isNotBlank(id),DeviceInspectionLine::getFormId, id));
		}
		//设备整改待办明细数据
		if ("2".equals(type)){
			deviceInspectionLineList = deviceInspectionLineService.list(new QueryWrapper<DeviceInspectionLine>().lambda()
				.eq(Func.isNotBlank(id),DeviceInspectionLine::getFormId, id)
//				.eq(DeviceInspectionLine::getStatus,Constant.DEVICE_STATE_RECTIFY)
				.eq(DeviceInspectionLine::getRecFlag,Constant.PROBLEM_STATE_USUUAL));
		}
		//设备持续整改待办明细数据
		if ("3".equals(type)){
			deviceInspectionLineList = deviceInspectionLineService.list(new QueryWrapper<DeviceInspectionLine>().lambda()
				.eq(Func.isNotBlank(id),DeviceInspectionLine::getId, id)
//				.eq(DeviceInspectionLine::getStatus,Constant.DEVICE_STATE_RECTIFY)
				.eq(DeviceInspectionLine::getRecFlag,Constant.PROBLEM_STATE_CONTINUED));
		}
		return setAppDeviceCheckItemVOS(deviceInspectionLineList);
	}

	/**
	 * 给设备检查或整改项返回值赋值
	 */
	private ArrayList<AppDeviceCheckItemVO> setAppDeviceCheckItemVOS(List<DeviceInspectionLine> deviceInspectionLineList) {
		ArrayList<AppDeviceCheckItemVO> list = new ArrayList<>();
		if (Func.isNotEmpty(deviceInspectionLineList)) {
			deviceInspectionLineList.forEach(item -> {
				AppDeviceCheckItemVO itemVO = Func.copy(item, AppDeviceCheckItemVO.class);
				list.add(itemVO);
			});
		}
		return list;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean handInDevice(AppDeviceCheckDTO appDeviceCheckDTO) {

		//筛选出检查结果状态为告警的数据
		List<AppDeviceDTO> collect = appDeviceCheckDTO.getAppDeviceDTOList().stream().filter(item -> Constant.DEVICE_PROBLEM_WARN.equals(item.getProblemLevel())).collect(Collectors.toList());
		//更新设备检查主表状态
		DeviceInspection deviceInspection = deviceInspectionService.getById(appDeviceCheckDTO.getId());
		deviceInspection.setStatus(Func.isNotEmpty(collect) ? Constant.DEVICE_STATE_RECTIFY : Constant.DEVICE_STATE_INSPECTION);
		deviceInspection.setRemark(Func.isNotEmpty(appDeviceCheckDTO.getRemark()) ? appDeviceCheckDTO.getRemark() : "无");
		deviceInspection.setInspectUser(String.valueOf(AuthUtil.getUser().getUserId()));
		//更新基础信息设备状态及最新检查时间
		Device device = deviceService.getById(deviceInspection.getDeviceId());
		device.setState(device.getOrgState());
		device.setOrgState("");
		device.setLatestInspectionTime(new Date());
		if (Func.isNotEmpty(appDeviceCheckDTO.getAppDeviceDTOList())) {
			//更新设备检查明细信息
			appDeviceCheckDTO.getAppDeviceDTOList().forEach(this::updateDeviceItem);
		}
		//如果检查明细不存在异常明细项，则提报给领导确认
		if (Func.isEmpty(collect)) {
			deviceInspection.setState(Constant.HANDIN_STATE_AUDIT);
			R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.DEVICE_INSPECTION_KEY);
			if (definitionRes.isSuccess()) {
				deviceInspection.setProcessDefinitionId(definitionRes.getData().getId());
				deviceInspection.setInsProcessDefinitionId(definitionRes.getData().getId());
			} else {
				throw new ServiceException("开启流程失败");
			}
			R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
			if (!deptCategory.isSuccess()) {
				throw new ServiceException("查询部门类型失败，请检查后再试！");
			}
			String businessTable = FlowUtil.getBusinessTable(DeviceInspection.class);
			Kv variables = Kv.create()
				.set("deptCategory", deptCategory.getData())
				.set(ProcessConstant.BUSINESS_ID_KEY, deviceInspection.getId());
			R<BladeFlow> result = flowClient.startProcessInstanceById(deviceInspection.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(deviceInspection.getId())), variables);
			if (!result.isSuccess()) {
				deviceInspection.setProcessInstanceId(result.getData().getProcessInstanceId());
				deviceInspection.setInsProcessInstanceId(result.getData().getProcessInstanceId());
				throw new ServiceException("开启流程失败");
			}
		}
		return deviceInspectionService.updateById(deviceInspection) && deviceService.updateById(device);
	}

	/**
	 * 更新设备检查项
	 */
	private void updateDeviceItem(AppDeviceDTO item) {
		DeviceInspectionLine deviceInspectionLine = deviceInspectionLineService.getById(item.getId());
		deviceInspectionLine.setDeviceState(Constant.DEVICE_LINE_STATE_2);
		deviceInspectionLine.setProblemLevel(item.getProblemLevel());
		deviceInspectionLine.setRectificationStatus(item.getProblemLevel());
		deviceInspectionLine.setBeforePicIds(item.getBeforePicIds());
		deviceInspectionLine.setStatus(Constant.DEVICE_PROBLEM_NORMAL.equals(item.getProblemLevel()) ? Constant.DEVICE_STATE_INSPECTION_OVER : Constant.DEVICE_STATE_RECTIFY);
		deviceInspectionLine.setRecFlag(Constant.DEVICE_PROBLEM_NORMAL.equals(item.getProblemLevel()) ? null : Constant.PROBLEM_STATE_USUUAL);
		//保存整改前图片
		fileService.saveAttachments(item.getImgUrl(), item.getId());
		deviceInspectionLine.setResult(item.getResult());
		deviceInspectionLineService.updateById(deviceInspectionLine);
	}

	@Override
	public AppDeviceVO getDeviceRectifyDetail(String id) {
		//获取待整改设备的设备id
		DeviceInspection deviceInspection = deviceInspectionService.getOne(new QueryWrapper<DeviceInspection>().lambda().eq(Func.isNotBlank(id), DeviceInspection::getId, id)
			.eq(DeviceInspection::getStatus, Constant.DEVICE_STATE_RECTIFY));
		//获取设备信息
		AppDeviceVO deviceVO = getAppDeviceDetail(deviceInspection);
		deviceVO.setState("待整改");
		return deviceVO;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean rectifyDevice(AppDeviceCheckDTO appDeviceCheckDTO) {
		//更新设备整改主表状态
		DeviceInspection deviceInspection = deviceInspectionService.getById(appDeviceCheckDTO.getId());
		deviceInspection.setStatus(Constant.DEVICE_STATE_RECTIFY_OVER);
		//更新设备整改明细信息
		if (Func.isNotEmpty(appDeviceCheckDTO.getAppDeviceDTOList())) {
			appDeviceCheckDTO.getAppDeviceDTOList().forEach(item -> {
				DeviceInspectionLine deviceInspectionLine = deviceInspectionLineService.getById(item.getId());
				deviceInspectionLine.setRectificationStatus(item.getRectificationStatus());
				deviceInspectionLine.setRectifyResult(item.getRectifyResult());
				deviceInspectionLine.setAfterPicIds(item.getAfterPicIds());
				deviceInspectionLine.setRecFlag(Constant.PROBLEM_STATE_USUUAL);
				deviceInspectionLine.setStatus(Constant.DEVICE_STATE_RECTIFY);
				deviceInspectionLine.setState(Constant.HANDIN_STATE_AUDIT);
				//存储原纪录id
				deviceInspectionLineService.updateById(deviceInspectionLine);
				//保存整改后相关图片
				fileService.saveAttachments(item.getImgUrl(), item.getId());
				//判断该设备检查是否需要持续整改
				setContinuedRectify(item, deviceInspectionLine);
			});
		}
		//设备整改完成进入领导确认流程
		R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.DEVICE_INSPECTION_REC_KEY);
		if (definitionRes.isSuccess()) {
			deviceInspection.setProcessDefinitionId(definitionRes.getData().getId());
			deviceInspection.setRecProcessDefinitionId(definitionRes.getData().getId());
		} else {
			throw new ServiceException("开启流程失败");
		}
		R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
		if (!deptCategory.isSuccess()) {
			throw new ServiceException("查询部门类型失败，请检查后再试！");
		}
		String businessTable = FlowUtil.getBusinessTable(DeviceInspection.class);
		Kv variables = Kv.create()
			.set("deptCategory", deptCategory.getData())
			.set(ProcessConstant.BUSINESS_ID_KEY, deviceInspection.getId());
		R<BladeFlow> result = flowClient.startProcessInstanceById(deviceInspection.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(deviceInspection.getId())), variables);
		if (!result.isSuccess()) {
			throw new ServiceException("开启流程失败");
		}
		deviceInspection.setProcessInstanceId(result.getData().getProcessInstanceId());
		deviceInspection.setRecProcessInstanceId(result.getData().getProcessInstanceId());
		return deviceInspectionService.updateById(deviceInspection);
	}

	private void setContinuedRectify(AppDeviceDTO item, DeviceInspectionLine deviceInspectionLine) {
		if (Func.isNotEmpty(item.getRecordFlag()) && Constant.PROBLEM_STATE_CONTINUED.equals(item.getRecordFlag())){
			deviceInspectionLine.setId(null);
			deviceInspectionLine.setRecFlag(Constant.PROBLEM_STATE_CONTINUED);
			deviceInspectionLine.setRectificationDeadline(item.getRectificationDeadline());
			deviceInspectionLine.setStatus(Constant.DEVICE_STATE_LEADER_CONFIRM);
			deviceInspectionLine.setDeptId(AuthUtil.getDeptId());
			deviceInspectionLine.setState(Constant.HANDIN_STATE_DRAFT);
			deviceInspectionLineService.save(deviceInspectionLine);
			//保存相关附件
			fileService.saveAttachments(item.getImgUrl(),deviceInspectionLine.getId());
		}
	}

	@Override
	public AppDeviceVO getContinuedRectifyDetail(String id) {
		//获取设备整改明细信息
		DeviceInspectionLine deviceInspectionLine = deviceInspectionLineService.getById(id);
		DeviceInspection deviceInspection = deviceInspectionService.getById(deviceInspectionLine.getFormId());
		AppDeviceVO appDeviceVO = getAppDeviceDetail(deviceInspection);
		appDeviceVO.setState("持续整改");
		return appDeviceVO;
	}

	@Override
	public boolean continuedRectifyHandIn(AppDeviceCheckDTO appDeviceCheckDTO) {
		//判断持续整改明细是否需要再次申请持续整改
		if (Func.isNotEmpty(appDeviceCheckDTO.getAppDeviceDTOList())){
			appDeviceCheckDTO.getAppDeviceDTOList().forEach(item -> {
				DeviceInspectionLine deviceInspectionLine = deviceInspectionLineService.getById(item.getId());
				deviceInspectionLine.setStatus(Constant.DEVICE_STATE_RECTIFY_OVER);
				deviceInspectionLine.setRectifyResult(item.getRectifyResult());
				//存储原纪录id
				deviceInspectionLineService.updateById(deviceInspectionLine);
				R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.DEVICE_INS_REC_CON_KEY);
				if (definitionRes.isSuccess()) {
					deviceInspectionLine.setProcessDefinitionId(definitionRes.getData().getId());
				} else {
					throw new ServiceException("开启流程失败");
				}
				R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
				if (!deptCategory.isSuccess()) {
					throw new ServiceException("查询部门类型失败，请检查后再试！");
				}
				String businessTable = FlowUtil.getBusinessTable(DeviceInspectionLine.class);
				Kv variables = Kv.create()
					.set("deptCategory", deptCategory.getData())
					.set(ProcessConstant.BUSINESS_ID_KEY, deviceInspectionLine.getId());
				R<BladeFlow> result = flowClient.startProcessInstanceById(deviceInspectionLine.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(deviceInspectionLine.getId())), variables);
				if (!result.isSuccess()) {
					deviceInspectionLine.setProcessInstanceId(result.getData().getProcessInstanceId());
					throw new ServiceException("开启流程失败");
				}
				//再次发起持续整改
				setContinuedRectify(item,deviceInspectionLine);
			});
		}
		return true;
	}
}
