/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.security.trans.dailyDuties.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.security.common.Constant;
import org.security.flow.core.constant.ProcessConstant;
import org.security.trans.app.vo.BacklogVO;
import org.security.ht.entity.basic.Department;
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.dto.DeviceInspectionDTO;
import org.security.trans.dailyDuties.dto.DeviceInspectionLineDTO;
import org.security.trans.dailyDuties.entity.DeviceInspection;
import org.security.trans.dailyDuties.entity.DeviceInspectionLine;
import org.security.trans.dailyDuties.mapper.DeviceInspectionMapper;
import org.security.trans.dailyDuties.service.IDeviceInspectionLineService;
import org.security.trans.dailyDuties.service.IDeviceInspectionService;
import org.security.trans.dailyDuties.service.IInspectionService;
import org.security.trans.dailyDuties.vo.DeviceInspectionLineVO;
import org.security.trans.dailyDuties.vo.DeviceInspectionVO;
import org.security.trans.dataStatistics.dto.DeviceInspectionDataDTO;
import org.security.trans.dataStatistics.vo.DeviceInspectionDataVO;
import org.security.trans.feign.UserFeignClient;
import org.security.trans.settings.entity.DeviceInspectionSettings;
import org.security.trans.settings.service.IDeviceInspectionSettingsService;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static org.security.common.Constant.*;

/**
 * 任务-设备检查表 服务实现类
 *
 * @author BladeX
 * @since 2022-03-25
 */
@Slf4j
@Service
@AllArgsConstructor
public class DeviceInspectionServiceImpl extends ServiceImpl<DeviceInspectionMapper, DeviceInspection> implements IDeviceInspectionService {
	private final IDeviceInspectionLineService deviceInspectionLineService;
	private final IDeviceService deviceService;
	private final IDeviceInspectionSettingsService deviceInspectionSettingsService;
	private final IDepartmentService departmentService;
	private final UserFeignClient userFeignClient;
	private final IFileService fileService;
	private final IInspectionService iInspectionService;

	@Override
	public IPage<DeviceInspectionVO> selectDeviceInspectionPage(IPage<DeviceInspectionVO> page, DeviceInspectionDTO deviceInspectionDTO) {
		String deptId = null;
		if (StringUtils.isNotBlank(deviceInspectionDTO.getDeptId())) {
			List<String> strList = Func.toStrList(deviceInspectionDTO.getDeptId());
			deptId = strList.get(strList.size() - 1);
		}
		Page<DeviceInspection> queryPage = new Page<>(page.getCurrent(), page.getSize());
		QueryWrapper<DeviceInspection> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda()
			.eq(DeviceInspection::getDelFlag, DELETE_FLAG_0)
			.eq(StringUtils.isNotBlank(deptId), DeviceInspection::getDeptId, deptId)
			.eq(StringUtils.isNotBlank(deviceInspectionDTO.getStatus()), DeviceInspection::getStatus, deviceInspectionDTO.getStatus())
			.like(StringUtils.isNotBlank(deviceInspectionDTO.getDeviceName()), DeviceInspection::getDeviceName, deviceInspectionDTO.getDeviceName())
			.orderByDesc(DeviceInspection::getCreatedTime);
		IPage<DeviceInspection> resultPage = this.baseMapper.selectDeviceInspectionPage(queryPage, queryWrapper);
		//获取设备持续整改记录
		List<DeviceInspectionVO> continuedRectifyList = deviceInspectionLineService.getContinuedRectifyData();
		List<DeviceInspection> records = resultPage.getRecords();
		List<DeviceInspectionVO> deviceInspectionVOList = Func.copy(records, DeviceInspectionVO.class);
		deviceInspectionVOList.addAll(continuedRectifyList);
		if (Func.isNotEmpty(deviceInspectionVOList)){
			deviceInspectionVOList.forEach(item ->{
				if (Func.isEmpty(item.getRectifyFlag()) && (Constant.DEVICE_STATE_INSPECTION.equals(item.getStatus()) || Constant.DEVICE_STATE_INSPECTION_OVER.equals(item.getStatus()) || Constant.DEVICE_STATE_OVERTIME_INSPECTION.equals(item.getStatus()))){
					item.setRectifyFlag("3");
				}
				if (Func.isEmpty(item.getRectifyFlag()) && (Constant.DEVICE_STATE_RECTIFY.equals(item.getStatus()) || Constant.DEVICE_STATE_RECTIFY_OVER.equals(item.getStatus()))){
					item.setRectifyFlag(Constant.PROBLEM_STATE_USUUAL);
				}
				//检查负责部门
				if(Func.isNotEmpty(item.getDeptId())){
					Department department = departmentService.getById(item.getDeptId());
					item.setDepName(Func.isNotEmpty(department) ? department.getDeptName() : null);
				}
				//设备所属部门
				item.setDeptName(departmentService.getById(deviceService.getById(item.getDeviceId()).getDepId()).getDeptName());
				//检查负责人和设备编号
				getInspectUser(item);
			});
		}
		return new Page<DeviceInspectionVO>()
			.setRecords(deviceInspectionVOList)
			.setSize(resultPage.getSize())
			.setTotal(resultPage.getTotal())
			.setCurrent(resultPage.getCurrent());
	}

	/**
	 *获取检查负责人和设备编号
	 */
	private void getInspectUser(DeviceInspectionVO item) {
		item.setDeviceNum(deviceService.getById(item.getDeviceId()).getDeviceNum());
		if(Func.isNotEmpty(item.getInspectUser())){
			ArrayList<String> userList = new ArrayList<>();
			List<String> list = Arrays.asList(item.getInspectUser().split(","));
			list.forEach(userId -> {
				String name = userFeignClient.getUserDetail(Long.valueOf(userId)).getData().getName();
				userList.add(name);
			});
			item.setInspectUserName(Func.join(userList,","));
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeDeviceInspectionAndLineByIds(List<Long> toLongList) {
		List<String> ids = Func.copy(toLongList, String.class);
		ids.forEach(formId -> {
			QueryWrapper<DeviceInspectionLine> queryWrapper = new QueryWrapper<>();
			queryWrapper.lambda().eq(DeviceInspectionLine::getFormId, formId);
			deviceInspectionLineService.remove(queryWrapper);
		});
		return this.removeByIds(ids);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R createDeviceInspection(DeviceInspectionDTO deviceInspectionDTO) {
		log.info("==============发起设备检查==============");
		//获取需要检查的设备id
		List<String> ids = Func.toStrList(deviceInspectionDTO.getIds());
		//获取需要检查且状态不在检查中的设备
		List<Device> deviceList = deviceService.list(new QueryWrapper<Device>().lambda().in(Func.isNotEmpty(ids),Device::getId,ids));
		List<DeviceInspectionLine> deviceInspectionLineList = new ArrayList<>();
		log.info("需要检查的设备个数[{}]" , deviceList.size());
		if (Func.isNotEmpty(deviceList)) {
			//设备信息赋值给设备检查实体
			deviceList.forEach(item -> {
				//更新设备表中的设备状态
//				updateDeviceState(item);
				//创建设备检查记录
				DeviceInspection deviceInspection = saveDeviceInspection(deviceInspectionDTO, item);
				//获取设备的类型层级
				getOriDeviceLevel(deviceInspectionLineList, item, deviceInspection);
			});
		}
		if(deviceInspectionLineList.size()>0){
			return R.status(deviceInspectionLineService.saveBatch(deviceInspectionLineList)) ;
		}
		log.info("==============发起设备检查结束==============");
		return R.success("操作成功");
	}

	/**
	 * 获取设备的类型层级
	 */
	private void getOriDeviceLevel(List<DeviceInspectionLine> deviceInspectionLineList, Device item, DeviceInspection deviceInspection) {
		List<String> typeIds = Func.toStrList(item.getTypeRank());
		List<DeviceInspectionLine> itemInspectionLineList = new ArrayList<>();//记录仅当前设备的检查项
		//根据设备类型层级，循环查询设备检查项表
		typeIds.forEach(typeId -> {
			QueryWrapper<DeviceInspectionSettings> queryWrapper = new QueryWrapper<>();
			queryWrapper.lambda().eq(DeviceInspectionSettings::getDeviceCatgId, typeId);
			//获取设备检查项
			List<DeviceInspectionSettings> settingsList = deviceInspectionSettingsService.list(queryWrapper);
			if(settingsList.size()>0){
				settingsList.forEach(setting -> {
					DeviceInspectionLine deviceInspectionLine = new DeviceInspectionLine();
					deviceInspectionLine.setFormId(deviceInspection.getId());
					deviceInspectionLine.setName(setting.getName());
					deviceInspectionLine.setDeviceState(DEVICE_LINE_STATE_0);
					deviceInspectionLine.setStatus(Constant.DEVICE_STATE_INSPECTION);
					deviceInspectionLine.setState(Constant.HANDIN_STATE_DRAFT);
					deviceInspectionLine.setDeptId(deviceInspection.getDeptId());
					deviceInspectionLine.setDeptName(deviceInspection.getDeptName());
					itemInspectionLineList.add(deviceInspectionLine);
					deviceInspectionLineList.add(deviceInspectionLine);
				});
			}
		});
		if(itemInspectionLineList.size()<1){
			log.info("-----当前设备【{}-{}】无法查询到对应的设备检查项",item.getName(),item.getId());
			throw new ServiceException(StringUtil.format("设备【{}-{}】无法查询到对应的设备检查项", item.getName(),item.getDeviceNum()));
		}
	}

	/**
	 *创建设备检查记录
	 */
	private DeviceInspection saveDeviceInspection(DeviceInspectionDTO deviceInspectionDTO, Device item) {
		DeviceInspection deviceInspection = new DeviceInspection();
		deviceInspection.setDeviceId(item.getId());
		deviceInspection.setDeviceName(item.getName());
		deviceInspection.setDeviceModelNum(item.getModelNum());
		deviceInspection.setState(Constant.HANDIN_STATE_DRAFT);
		deviceInspection.setInspectUser(deviceInspectionDTO.getInspectUser());
		deviceInspection.setAuditUser(deviceInspectionDTO.getAuditUser());
		//检查发起部门
		deviceInspection.setCreateDeptId(AuthUtil.getDeptId());
		//所属部门
		deviceInspection.setDeptId(item.getDepId());
		deviceInspection.setDeptName(departmentService.getById(deviceInspection.getDeptId()).getDeptName());
		deviceInspection.setStatus(Constant.DEVICE_STATE_INSPECTION);
		deviceInspection.setCheckDeadline(deviceInspectionDTO.getCheckDeadline());
		this.save(deviceInspection);
		return deviceInspection;
	}

	/**
	 *更新设备表中的设备状态
	 */
	private void updateDeviceState(Device item) {
		//存放原状态
		item.setOrgState(item.getState());
		//把设备状态设为检查中并更新设备表
		item.setState(DEVICE_STATE_INSPECTION);
		deviceService.updateById(item);
	}

	@Override
	public DeviceInspection getDeviceIns(String deviceId, Date start, Date end) {
		QueryWrapper<DeviceInspection> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("DEVICE_ID", deviceId);
		queryWrapper.ge("CREATED_TIME", start);
		queryWrapper.le("CREATED_TIME", end);
		return baseMapper.selectOne(queryWrapper);
	}

	@Override
	public List<BacklogVO> getAppBacklog(BladeUser user, List<String> list) {
		log.info("========getAppBacklog user:{}",user);
		log.info("========getAppBacklog list:{}",list);
		return baseMapper.getAppBacklog(String.valueOf(user.getDeptId()), list);
	}

	@Override
	public List<DeviceInspection> getDeadlineCheckList() {
		QueryWrapper<DeviceInspection> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("STATUS", Constant.DEVICE_STATE_INSPECTION);
		queryWrapper.eq("DEL_FLAG",Constant.DELETE_FLAG_0);
		return baseMapper.selectList(queryWrapper);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public DeviceInspectionLineVO changeStateById(DeviceInspectionLineDTO deviceInspectionLineDTO) {
		DeviceInspectionLineVO vo = new DeviceInspectionLineVO();
		List<String> idList = Func.toStrList(deviceInspectionLineDTO.getIds());
		List<DeviceInspectionLine> deviceInspectionLineList = deviceInspectionLineService.listByIds(idList);
		deviceInspectionLineList.forEach(item -> item.setDeviceState(DEVICE_LINE_STATE_2));
		deviceInspectionLineService.updateBatchById(deviceInspectionLineList);
		QueryWrapper<DeviceInspectionLine> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(DeviceInspectionLine::getFormId, deviceInspectionLineDTO.getFormId());
		List<DeviceInspectionLine> updateAfterList = deviceInspectionLineService.list(queryWrapper);
		int count = 0;
		for (DeviceInspectionLine deviceInspectionLine : updateAfterList) {
			if (DEVICE_LINE_STATE_2.equals(deviceInspectionLine.getDeviceState())) {
				count++;
			}
		}
		if (count == updateAfterList.size()) { //判断设备的检查项是否都检查完成
			//查询设备检查主表
			QueryWrapper<DeviceInspection> inspectionQueryWrapper = new QueryWrapper<>();
			inspectionQueryWrapper.lambda().eq(DeviceInspection::getId, deviceInspectionLineDTO.getFormId());
			DeviceInspection deviceInspection = this.getOne(inspectionQueryWrapper);
			deviceInspection.setStatus(DEVICE_STATE_INSPECTION_OVER);
			//查询设备表
			QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
			deviceQueryWrapper.lambda().eq(Device::getId, deviceInspection.getDeviceId());
			Device device = deviceService.getOne(deviceQueryWrapper);
			device.setState(device.getOrgState()); //检查完成，还原设备状态
			device.setOrgState("");
			this.updateById(deviceInspection);//更新设备检查表主表
			deviceService.updateById(device);//更新设备表
			vo.setOverFlag(true);
		}
		vo.setOverFlag(false);
		return vo;
	}

	@Override
	public DeviceInspectionVO getData(String id) {
		DeviceInspection deviceInspection = this.getById(id);
		DeviceInspectionVO inspectionVO = Func.copy(deviceInspection, DeviceInspectionVO.class);
		inspectionVO.setDepName(iInspectionService.getDeptData(deviceInspection.getDeptId()));
		getInspectUser(inspectionVO);
		//获取设备检查相关明细
		List<DeviceInspectionLine> list = deviceInspectionLineService.list(new QueryWrapper<DeviceInspectionLine>().lambda().eq(Func.isNotEmpty(id), DeviceInspectionLine::getFormId, id)
			.ne(DeviceInspectionLine::getRecFlag,Constant.PROBLEM_STATE_CONTINUED));
		if (Func.isNotEmpty(list)) {
			List<DeviceInspectionLineVO> inspectionLineList = Func.copy(list, DeviceInspectionLineVO.class);
			inspectionLineList.forEach(item -> {
				//获取整改前图片
				item.setBeforeImages(fileService.getAttachments(item.getId(),item.getBeforePicIds()));
				//获取整改后图片
				item.setBeforeImages(fileService.getAttachments(item.getId(),item.getAfterPicIds()));
			});
			inspectionVO.setDeviceInspectionLines(inspectionLineList);
		}

		return inspectionVO;
	}

	@Override
	public List<DeviceInspectionDataVO> getAimStatisticsData(DeviceInspectionDataDTO deviceInspectionDataDTO, List<String> aimDepts) {
		return baseMapper.getAimStatisticsData(deviceInspectionDataDTO,aimDepts);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public R afterFlowFinished(String id, Boolean pass, Map<String, Object> variables) {
		Boolean result = false;
		String state;
		if (null == pass) {
			state = ProcessConstant.CANCEL_STATE;
		} else if (pass) {
			state = ProcessConstant.PASS_STATE;
		} else {
			state = ProcessConstant.REJECT_STATE;
		}
		result = this.updateStateById(id, state);
		if (result) {
			DeviceInspection deviceInspection = this.getById(id);
			//筛选出持续整改记录
			List<DeviceInspectionLine> list = deviceInspectionLineService.list(new QueryWrapper<DeviceInspectionLine>().lambda().eq(Func.isNotEmpty(id), DeviceInspectionLine::getFormId, id));
			List<String> collect = new ArrayList<>();
			if (Func.isNotEmpty(list)){
				collect = list.stream().filter(item -> Constant.PROBLEM_STATE_CONTINUED.equals(item.getRecFlag())
					&& Constant.DEVICE_STATE_LEADER_CONFIRM.equals(item.getStatus())).map(DeviceInspectionLine::getId).collect(Collectors.toList());
			}
			//审批通过
			log.info("----------------------------持续整改记录的id[{}]-----------------------------",collect);
			if (Func.isNotEmpty(pass) && pass) {
				//设备检查无异常审批通过
				if (Constant.DEVICE_STATE_INSPECTION.equals(deviceInspection.getStatus())) {
					log.info("设备检查审批通过");
					deviceInspection.setStatus(Constant.DEVICE_STATE_INSPECTION_OVER);
				}
				//设备整改提报审批通过
				if (Constant.DEVICE_STATE_RECTIFY.equals(deviceInspection.getStatus())) {
					log.info("设备整改审批通过");
					deviceInspection.setStatus(Constant.DEVICE_STATE_RECTIFY_OVER);
				}
				//审批通过变更持续整改记录状态为待整改
				if (Func.isNotEmpty(collect)){
					log.info("设备持续整改明细[{}]",collect);
					deviceInspectionLineService.update(new UpdateWrapper<DeviceInspectionLine>().lambda().set(DeviceInspectionLine::getStatus, Constant.DEVICE_STATE_RECTIFY).in(DeviceInspectionLine::getId, collect));
				}
			}else {
				if (Constant.DEVICE_STATE_RECTIFY.equals(deviceInspection.getStatus())) {
					deviceInspection.setStatus(Constant.DEVICE_STATE_RECTIFY);
				}
				//审批拒绝或撤回，若审批记录明细存在持续整改申请记录，删除该明细
				if (Func.isNotEmpty(collect)){
					deviceInspectionLineService.removeByIds(collect);
				}
			}
			this.updateById(deviceInspection);
		}
		return R.success("执行成功");
	}
}
