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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.common.util.ExcelUtil;
import org.security.ht.vo.common.UploadVO;
import org.security.trans.basic.dto.DeviceDTO;
import org.security.ht.entity.basic.Department;
import org.security.ht.entity.basic.Device;
import org.security.trans.basic.dto.DeviceExcelDTO;
import org.security.trans.basic.mapper.DeviceMapper;
import org.security.trans.basic.service.IDepartmentService;
import org.security.trans.basic.service.IDeviceService;
import org.security.ht.vo.basic.DeviceVO;
import org.security.trans.common.service.IFileService;
import org.security.trans.dailyDuties.dto.InspectionLineExcelDTO;
import org.security.trans.dailyDuties.entity.DeviceInspection;
import org.security.trans.dailyDuties.entity.InspectionLine;
import org.security.trans.dataStatistics.entity.DeviceData;
import org.security.trans.settings.entity.DeviceCategorySettings;
import org.security.trans.settings.service.IDeviceCategorySettingsService;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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

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

/**
 * 基础信息-设备信息 服务实现类
 *
 * @author BladeX
 * @since 2022-03-16
 */
@Service
@Scope("prototype")
@AllArgsConstructor
@Slf4j
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService {

	private IDepartmentService departmentService;

	private IDeviceCategorySettingsService deviceCategorySettingsService;

	private final IFileService fileService;

	@Override
	public IPage<DeviceVO> selectDevicePage(IPage<DeviceVO> page, DeviceDTO deviceDto) {
		String depId = null;
		if (StringUtils.isNotBlank(deviceDto.getDepId())) {
			List<String> depIdList = Func.toStrList(deviceDto.getDepId());
			depId = depIdList.get(depIdList.size() - 1);
		}
		Page<Device> devicePage = new Page<>(page.getCurrent(), page.getSize());
		QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
		deviceQueryWrapper.lambda().eq(Device::getDelFlag, DELETE_FLAG_0);
		//请求来自设备检查页面
		if ("0".equals(deviceDto.getFlag())) {
			deviceQueryWrapper.lambda()
				.eq(StringUtils.isNotBlank(depId), Device::getDepId, depId)
				.in(Device::getUsageState, DEVICE_STATE_DUSE, DEVICE_STATE_USE, DEVICE_STATE_OVERTIME_USE)
				.orderByAsc(Device::getDepId)
				.orderByAsc(Device::getDeviceNum);
		} else {
			deviceQueryWrapper.lambda()
				.eq(StringUtils.isNotBlank(depId), Device::getDepId, depId)
				.eq(StringUtils.isNotBlank(deviceDto.getState()), Device::getState, deviceDto.getState())
				.eq(StringUtils.isNotBlank(deviceDto.getUsageState()), Device::getUsageState, deviceDto.getUsageState())
				.eq(StringUtils.isNotBlank(deviceDto.getDeviceState()), Device::getDeviceState, deviceDto.getDeviceState())
				.like(StringUtils.isNotBlank(deviceDto.getTypeRank()), Device::getTypeRank, deviceDto.getTypeRank())
				.like(StringUtils.isNotBlank(deviceDto.getName()), Device::getName, deviceDto.getName())
				.orderByAsc(Device::getDepId)
				.orderByAsc(Device::getDeviceNum);
		}
		IPage<Device> resultPage = this.baseMapper.selectDevicePage(devicePage, deviceQueryWrapper);
		final List<Device> records = resultPage.getRecords();
		List<DeviceVO> deviceVOList = new ArrayList<>();
		if (!Func.isNull(records) && records.size() > 0) {
			records.forEach(item -> {
				DeviceVO deviceVO = Func.copy(item, DeviceVO.class);
				Department department = departmentService.getById(item.getDepId());
				deviceVO.setDeptName(!Func.isNull(department) ? department.getDeptName() : "");
				DeviceCategorySettings deviceCategorySettings = deviceCategorySettingsService.getById(item.getTypeId());
				deviceVO.setTypeName(!Func.isNull(deviceCategorySettings) ? deviceCategorySettings.getName() : "");
				assert deviceVO != null;
				deviceVOList.add(deviceVO);
			});
		}
		return new Page<DeviceVO>()
			.setSize(resultPage.getSize())
			.setCurrent(resultPage.getCurrent())
			.setTotal(resultPage.getTotal())
			.setRecords(deviceVOList);
	}

	@Override
	public DeviceVO getDeviceById(Long id) {
		Device device = this.getById(id);
		DeviceVO deviceVO = Func.copy(device, DeviceVO.class);
		assert deviceVO != null;
		List<String> typeRankList = Func.toStrList(device.getTypeRank());
		deviceVO.setTypeRankList(typeRankList);
		Department department = departmentService.getById(device.getDepId());
//		返回级联框显示所用的部门id list
		if(!Func.isNull(department)){
			List<Long> deptIdList = Func.toLongList(department.getAncestors());
			List<Long> collect = deptIdList.stream().filter(item -> !item.equals(deptIdList.get(0))).collect(Collectors.toList());
//			数据库存储的Ancestors顺序是祖辈级别越高越靠后，需要先进行逆序
			Collections.reverse(collect);
//			逆序后祖辈级id从高到低，此时再加上设备所属本级机构
			collect.add(department.getId());
			deviceVO.setDeptIdList(collect);
//			查询所属部门名称
			deviceVO.setDeptName(department.getDeptName());
		}
		deviceVO.setPicList(fileService.getAttachments(device.getId(),device.getGroupName()));
		return deviceVO;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveDevice(DeviceDTO deviceDTO) {
		List<String> typeRankList = Func.toStrList(deviceDTO.getTypeRank());
		if(Func.isNotEmpty(typeRankList)){
			deviceDTO.setTypeId(typeRankList.get(typeRankList.size() - 1));
		}
		if (Func.isEmpty(deviceDTO.getDepId())){
			deviceDTO.setDepId(AuthUtil.getDeptId());
		}
		Device device = Func.copy(deviceDTO, Device.class);
		//获取设备关联设备类型的检查频率
		if(Func.isNotEmpty(device.getTypeId())){
			DeviceCategorySettings deviceCategorySettings = deviceCategorySettingsService.getById(device.getTypeId());
			device.setFrequency(Func.isNotEmpty(deviceCategorySettings) ? deviceCategorySettings.getCheckFreq() : null);
		}
		this.saveOrUpdate(device);
		//若是新增，生成设备二维码所需字符串
		if(Func.isNull(device.getQrCode()) || Func.isBlank(device.getQrCode())){
			device.setQrCode(device.getId().concat("-").concat(Func.formatDateTime(new Date())));
			this.updateById(device);
		}
		//保存附件
		List<UploadVO> fileList = deviceDTO.getPicList();
		if (Objects.nonNull(fileList) && !fileList.isEmpty()) {
			fileService.saveAttachments(fileList, device.getId());
		}
		return true;
	}

	@Override
	public IPage<Device> getCheckList(Query query) {
		QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("STATE", DEVICE_STATE_DUSE, DEVICE_STATE_OVERTIME_USE,DEVICE_STATE_USE);
		Page<Device> page = new Page<>(query.getCurrent(), query.getSize());
		return baseMapper.selectPage(page, queryWrapper);
	}

	@Override
	public boolean createQrCode(List<Long> toLongList) {
		//生成base64格式二维码
//		HashMap<String, String> hashMap = new HashMap<>();
//		ArrayList<Device> list = new ArrayList<>();
//		if (Func.isNotEmpty(toLongList)){
//			toLongList.forEach(item->{
//				//生成二维码
//				String qrCode = QrCodeUtil.createQrCode(String.valueOf(item));
//				hashMap.put(String.valueOf(item),qrCode);
//				//根据id获取设备信息
//				Device device = this.getById(item);
//				list.add(device);
//			});
//			//更新设备二维码信息
//			if (Func.isNotEmpty(list)){
//				list.forEach(item->{
//					item.setQrCode(hashMap.get(item.getId()));
//				});
//			}
//			return this.saveOrUpdateBatch(list);
//		}
//		return false;

		//更新二维码
		ArrayList<Device> list = new ArrayList<>();
		if (Func.isNotEmpty(toLongList)) {
			toLongList.forEach(item -> {
				//根据id获取设备信息
				Device device = this.getById(item);
				list.add(device);
			});
		}
		//生成二维码所需字符串
		if (Func.isNotEmpty(list)) {
			list.forEach(item -> {
				item.setQrCode(item.getId().concat("-").concat(Func.formatDateTime(new Date())));
			});
		}
		return this.saveOrUpdateBatch(list);
	}

	@Override
	public R disposalByIds(List<Long> toLongList) {
		ArrayList<Device> list = new ArrayList<>();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String endDate = formatter.format(DateUtil.now());
		if (Func.isNotEmpty(toLongList)) {
			toLongList.forEach(item -> {
				//根据id获取设备信息
				Device device = this.getById(item);
				list.add(device);
			});
		}
		if (Func.isNotEmpty(list)) {
			list.forEach(item -> {
				item.setUsageState(DEVICE_STATE_DISPOSED);
				item.setEndDate(endDate);
			});
		}
		return R.status(this.saveOrUpdateBatch(list));
	}

	@Override
	public List<DeviceData> getRisSunChartData(List<String> aimDepts) {
		return baseMapper.getRisSunChartData(aimDepts);
	}
	@Override
	public List<DeviceData> getPieDeptData(String aimDept) {
		return baseMapper.getPieDataByDeptId(aimDept);
	}

	/**
	 * 导入设备
	 *
	 * @param file 文件内容
	 * @return
	 */
	@Override
	public R importData(MultipartFile file) {
		log.info("---------导入设备--------");
		ArrayList<Device> lines = new ArrayList<>();
		//读取excel文件内容
		List<DeviceExcelDTO> list = ExcelUtil.read(file, DeviceExcelDTO.class);
		if (Func.isNotEmpty(list)) {
			list.forEach(item -> {
				DeviceDTO device = Func.copy(item, DeviceDTO.class);
//				设备归属部门id,默认取当前登录人员所属部门
				device.setDepId(AuthUtil.getDeptId());
				device.setUsageState(DEVICE_STATE_DUSE);//设备使用状态 0-未投入使用 导入的设备没有设备类型，需要手动维护类型并更新为正常使用中
				device.setDeviceState("1");//设备状态 1-正常
//				lines.add(device);
				saveDevice(device);
			});
		}
		return R.success("导入成功");
	}

	@Override
	public List<Device> getUsingList(){
		QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("USAGE_STATE", DEVICE_STATE_USE);
		queryWrapper.eq("DEL_FLAG",Constant.DELETE_FLAG_0);
		return baseMapper.selectList(queryWrapper);
	}

	@Override
	public R removeDevice(List<Long> toLongList) {
		if (Func.isNotEmpty(toLongList)) {
			toLongList.forEach(item -> {
				String deviceId = String.valueOf(item);
				//查询该设备相关的未删除的设备检查记录
				List<DeviceInspection> deviceInspectionList = baseMapper.deviceInspectionList(deviceId);
				if(deviceInspectionList.size()>0){
					log.info("=====设备【{}】存在设备检查记录，无法删除",item);
					throw new ServiceException("当前设备存在设备检查记录，无法删除");
				}
			});
		}

		return R.status(this.removeByIds(toLongList));
	}
}
