/*
 *      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.securityCommandCenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.security.common.Constant;
import org.security.common.util.DataFormatUtil;
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.basic.service.IDepartmentService;
import org.security.trans.common.service.IFileService;
import org.security.trans.dailyDuties.service.IInspectionService;
import org.security.trans.dataStatistics.dto.StatisticsDataDTO;
import org.security.trans.dataStatistics.dto.UnlocaleCheckDataDTO;
import org.security.trans.dataStatistics.vo.UnlocaleCheckDataVO;
import org.security.trans.securityCommandCenter.dto.SccCheckDTO;
import org.security.trans.securityCommandCenter.dto.SccCheckLinesDTO;
import org.security.trans.securityCommandCenter.entity.SccCheck;
import org.security.trans.securityCommandCenter.entity.SccCheckLines;
import org.security.trans.securityCommandCenter.service.ISccCheckLinesService;
import org.security.trans.securityCommandCenter.service.ISccUnlocaleCheckService;
import org.security.trans.securityCommandCenter.vo.SccCheckLinesVO;
import org.security.trans.securityCommandCenter.vo.SccCheckVO;
import org.security.trans.securityCommandCenter.mapper.SccCheckMapper;
import org.security.trans.securityCommandCenter.service.ISccCheckService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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 com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 安保指挥长中心-营业网点检查和自主银行检查记录 服务实现类
 *
 * @author BladeX
 * @since 2022-07-06
 */
@Slf4j
@Service
@AllArgsConstructor
public class SccCheckServiceImpl extends ServiceImpl<SccCheckMapper, SccCheck> implements ISccCheckService {

	private final ISccCheckLinesService sccCheckLinesService;
	private final IDepartmentService departmentService;
	private final IFileService fileService;
	private final ISccUnlocaleCheckService sccUnlocaleCheckService;
	private final ISysClient sysClient;
	private final IFlowClient flowClient;
	private final IInspectionService iInspectionService;

	@Override
	public IPage<SccCheckVO> selectSccCheckPage(IPage<SccCheckVO> page, SccCheckDTO sccCheckDTO) {
		return page.setRecords(baseMapper.selectSccCheckPage(page, sccCheckDTO));
	}

	@Override
	public SccCheckVO getData(String id) {
		log.info("==============获取营业网点检查/自助银行检查日志详情开始==============");
		//获取营业网点检查或自助银行检查记录
		SccCheck sccCheck = this.getById(id);
		SccCheckVO checkVO = Func.copy(sccCheck, SccCheckVO.class);
		//获取营业网点检查或自助银行检查记录明细
		List<SccCheckLines> list = sccCheckLinesService.list(new QueryWrapper<SccCheckLines>().lambda().eq(Func.isNotEmpty(sccCheck.getId()), SccCheckLines::getFormId, sccCheck.getId()));
		checkVO.setSccCheckLinesList(Func.copy(list, SccCheckLinesVO.class));
		//获取营业网点检查或自助银行检查记录明细的相关附件
		checkVO.getSccCheckLinesList().forEach(item -> {
			item.setRelevantAttachments(fileService.getAttachments(item.getId(), null));
		});
		log.info("==============获取营业网点检查/自助银行检查日志详情结束==============");
		return checkVO;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean saveCheckData(SccCheckDTO sccCheckDTO) throws ParseException {
		log.info("==============营业网点检查/自助银行检查日志录入开始==============");
		//保存检查记录
		SccCheck sccCheck = Func.copy(sccCheckDTO, SccCheck.class);
		sccCheck.setDutyTime(DataFormatUtil.getLocalDate());
		sccCheck.setDeptId(AuthUtil.getDeptId());
		sccCheck.setState(Constant.HANDIN_STATE_AUDIT);
		sccCheck.setDeptName(iInspectionService.getDeptData(AuthUtil.getDeptId()));
		// 先save一次，获得id
		this.saveOrUpdate(sccCheck);
		//保存检查记录明细
		List<SccCheckLines> sccCheckLinesList = Func.copy(sccCheckDTO.getSccCheckLinesDTOList(), SccCheckLines.class);
		if (sccCheckLinesList.stream().filter(sccCheckLines -> Constant.CHECK_STATUS_ZERO.equals(sccCheckLines.getCheckStatus())).collect(Collectors.toList()).size() > 0) {
			R<BladeFlowDef> definitionRes = flowClient.getLatestProcessDefinitionByKey(ProcessConstant.SCC_CHECK_KEY);
			if (definitionRes.isSuccess()) {
				sccCheck.setProcessDefinitionId(definitionRes.getData().getId());
			} else {
				throw new ServiceException("开启流程失败");
			}
			String businessTable = FlowUtil.getBusinessTable(SccCheck.class);
			R<Integer> deptCategory = sysClient.getDeptCategory(Long.valueOf(AuthUtil.getUser().getDeptId()));
			if (!deptCategory.isSuccess()) {
				throw new ServiceException("查询部门类型失败，请检查后再试！");
			}
			Kv variables = Kv.create()
				.set("deptCategory", deptCategory.getData())
				.set(ProcessConstant.BUSINESS_ID_KEY, sccCheck.getId())
				.set(ProcessConstant.START_PROC_USER_ID, AuthUtil.getUserId());
			R<BladeFlow> result = flowClient.startProcessInstanceById(sccCheck.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(sccCheck.getId())), variables);
			if (result.isSuccess()) {
				log.debug("流程已启动,流程ID:" + result.getData().getProcessInstanceId());
				// 返回流程id写入dutyRecords
				sccCheck.setProcessInstanceId(result.getData().getProcessInstanceId());
			} else {
				throw new ServiceException("流程启动失败");
			}
		}
		this.updateById(sccCheck);
		if (Func.isNotEmpty(sccCheckLinesList)) {
			sccCheckLinesList.forEach(item -> {
				item.setFormId(sccCheck.getId());
				//给营业网点名称赋值
				item.setOutletsName(departmentService.getById(item.getOutletsCode()).getDeptName());
			});
		}
		sccCheckLinesService.saveOrUpdateBatch(sccCheckLinesList);
		log.info("==============营业网点检查/自助银行检查日志录入结束==============");
		return true;
	}

	/**
	 * 审批通过后回调该接口创建整改通知书
	 * @param id
	 * @return
	 */

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean createdCheackNotice(String id) {
		SccCheck sccCheck = this.getById(id);
		List<SccCheckLines> list = sccCheckLinesService.list(new QueryWrapper<SccCheckLines>().lambda().eq(Func.isNotEmpty(id), SccCheckLines::getFormId, id));
		//若安防设施设备运行情况/自助机具及安防设施设备运行情况存在异常状态则发起检查整改通知书
		List<SccCheckLines> collect = list.stream().filter(item -> Constant.CHECK_STATUS_ZERO.equals(item.getCheckStatus())).collect(Collectors.toList());
		if (Func.isNotEmpty(collect)) {
			return sccUnlocaleCheckService.startRectedNotice(sccCheck, collect);
		}
		return false;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean removeData(List<Long> toLongList) {
		log.info("==============营业网点检查/自助银行检查日志删除开始==============");
		//删除检查记录
		this.removeByIds(toLongList);
		//删除检查记录相关明细
		List<String> list = new ArrayList<>();
		toLongList.forEach(item ->{
			SccCheckLines sccCheckLines = sccCheckLinesService.getById(item);
			list.add(sccCheckLines.getId());
		});
		boolean b = sccCheckLinesService.removeByIds(list);
		//删除检查记录明细相关附件
		boolean b1 = fileService.removeFileData(list);
		log.info("==============营业网点检查/自助银行检查日志删除结束==============");
		return b && b1;
	}

	@Override
	public IPage<SccCheckLinesVO> selectDetailPage(IPage<SccCheckLinesVO> page, SccCheckLinesDTO sccCheckLinesDTO) {
		log.info("==============获取营业网点检查/自助银行检查日志开始==============");
		List<SccCheckLinesVO> list;
		//获取检查结果异常项列表
		list = sccCheckLinesService.selectDetailPage(page,sccCheckLinesDTO);
		if (Func.isNotEmpty(list)){
			list.forEach(item -> {
				SccCheck sccCheck = this.getById(item.getFormId());
				item.setPersonOnDuty(sccCheck.getPersonOnDuty());
				item.setDutyTime(sccCheck.getDutyTime());
				item.setCheckType(sccCheck.getCheckType());
				//前端按钮控制筛选：当前登录机构是问题整改机构则有查看和编辑功能，当前登录机构不是问题整改机构则只有查看功能
				item.setButtonStatus(item.getOutletsCode().equals(AuthUtil.getDeptId()) ? Constant.BUTTON_STATE_ONE : Constant.BUTTON_STATE_THREE);
			});
		}
		//根据前端页面筛选出营业网点检查或自助银行检查的数据数据
		list = list.stream().filter(item -> item.getCheckType().equals(sccCheckLinesDTO.getCheckType())).collect(Collectors.toList());
		//如果查询筛选条件值班人员不为空
		if (Func.isNotBlank(sccCheckLinesDTO.getPersonOnDuty())){
			list = list.stream().filter(item -> item.getPersonOnDuty().equals(sccCheckLinesDTO.getPersonOnDuty())).collect(Collectors.toList());
		}
		//如果查询筛选条件值班时间不为空
		if (Func.isNotEmpty(sccCheckLinesDTO.getDutyTime())) {
			list = list.stream().filter(item -> item.getDutyTime().equals(sccCheckLinesDTO.getDutyTime())).collect(Collectors.toList());
		}
		log.info("==============获取营业网点检查/自助银行检查日志结束==============");
		return page.setRecords(list);
	}

	@Override
	public List<UnlocaleCheckDataVO> getAimStatisticsData(UnlocaleCheckDataDTO unlocaleCheckDataDTO, List<String> aimDepts) {
		return baseMapper.getAimStatisticsData(unlocaleCheckDataDTO,aimDepts);
	}

}
