package com.railway.business.safetool.service.impl;

import com.railway.business.safetool.domain.BaseSafetyTool;
import com.railway.business.safetool.domain.SecExperiment;
import com.railway.business.safetool.domain.SecScheduled;
import com.railway.business.safetool.enums.ToolStateEnum;
import com.railway.business.safetool.enums.ToolTestStateEnum;
import com.railway.business.safetool.mapper.BaseSafetyToolMapper;
import com.railway.business.safetool.mapper.SecExperimentMapper;
import com.railway.business.safetool.mapper.SecScheduledMapper;
import com.railway.business.safetool.service.IBaseSafetyToolService;
import com.railway.common.core.domain.AjaxResult;
import com.railway.common.core.domain.entity.SysUser;
import com.railway.common.enums.QcodeEnum;
import com.railway.common.qrcode.impl.SnowflakeClient;
import com.railway.common.utils.DateUtils;
import com.railway.common.utils.QrCodeUtil;
import com.railway.common.utils.SecurityUtils;
import com.railway.common.utils.StringUtils;
import com.railway.common.utils.ZipUtil;
import com.railway.common.utils.file.FileUploadUtils;
import com.railway.common.utils.http.HttpUtils;
import com.railway.system.service.ISysDictDataService;
import com.railway.system.service.ISysFileService;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 安全工具-基础数据
 *
 * @author wuhonghao
 * @date 2021/12/01
 */
@Slf4j
@Service
public class BaseSafetyToolServiceImpl implements IBaseSafetyToolService {

  /**
   * 上传文件存储在本地的根路径
   */
  @Value("${railway.filePath}")
  private String localFilePath;

  private final ISysFileService sysFileService;
  private final BaseSafetyToolMapper safetyToolMapper;
  private final SecExperimentMapper experimentMapper;
  private final SecScheduledMapper scheduledMapper;
  private final SnowflakeClient snowflakeClient;
  private final ISysDictDataService dictDataService;
  private final ISysFileService fileService;


  public BaseSafetyToolServiceImpl(ISysFileService sysFileService,
      BaseSafetyToolMapper safetyToolMapper,
      SecExperimentMapper experimentMapper,
      SecScheduledMapper scheduledMapper,
      SnowflakeClient snowflakeClient,
      ISysDictDataService dictDataService, ISysFileService fileService) {
    this.sysFileService = sysFileService;
    this.safetyToolMapper = safetyToolMapper;
    this.experimentMapper = experimentMapper;
    this.scheduledMapper = scheduledMapper;
    this.snowflakeClient = snowflakeClient;
    this.dictDataService = dictDataService;
    this.fileService = fileService;
  }

  /**
   * 新增
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public int create(BaseSafetyTool baseSafetyTool) {
    baseSafetyTool.setCreateTime(new Date());
    baseSafetyTool.setCreateBy(SecurityUtils.getUsername());
    baseSafetyTool.setState(ToolStateEnum.NORMAL.getCode());
    setTool(baseSafetyTool);
    return safetyToolMapper.insert(baseSafetyTool);
  }

  /**
   * 删除
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public int delete(Long[] toolIds) {
    int r = 0;
    for (Long toolId : toolIds) {
      int j = safetyToolMapper.delete(toolId);
      r = r + j;
    }
    return r;
  }

  /**
   * 更新
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public int update(BaseSafetyTool baseSafetyTool) {
    baseSafetyTool.setUpdateTime(new Date());
    baseSafetyTool.setUpdateBy(SecurityUtils.getUsername());
    return safetyToolMapper.update(baseSafetyTool);
  }

  /**
   * 获取单个
   */
  @Override
  public BaseSafetyTool getInfo(Long toolId) {
    return safetyToolMapper.getInfo(toolId);
  }

  /**
   * 获取单个
   */
  @Override
  public BaseSafetyTool getInfoByQcode(String qcode) {
    return safetyToolMapper.getInfoByQcode(qcode);
  }

  /**
   * 获取单个
   */
  @Override
  public void setBaseSafetyTool(BaseSafetyTool tool) {
    // 查询该工具相关的 待送检 计划
    List<SecScheduled> scheduledList = scheduledMapper.listScheduled(tool.getToolId());
    if(CollectionUtils.isNotEmpty(scheduledList)){
      tool.setScheduledId(scheduledList.get(0).getId());
      tool.setTestState(ToolTestStateEnum.NOT_CONFIRM.getCode());
      return;
    }
    // 查询该工具相关的 待实验 送检记录
    List<SecExperiment> experimentList = experimentMapper.listExperiment(tool.getToolId());
    if (CollectionUtils.isNotEmpty(experimentList)) {
      tool.setExperimentId(experimentList.get(0).getId());
      tool.setTestState(ToolTestStateEnum.CONFIRM.getCode());
      return;
    }
    // 既没有在计划中，也没有待实验的送检记录，表示该工具没有计划，可以增加到计划中
    tool.setTestState(ToolTestStateEnum.NO_PLAN.getCode());
  }

  /**
   * 查询列表
   */
  @Override
  public List<BaseSafetyTool> getList(BaseSafetyTool baseSafetyTool) {
    Long userId = SecurityUtils.getUserId();
    if (!SysUser.isAdmin(userId)) {
      baseSafetyTool.setDeptId(SecurityUtils.getDeptId());
    }
    List<BaseSafetyTool> list = safetyToolMapper.getList(baseSafetyTool);
    for(BaseSafetyTool tool : list){
      if(StringUtils.isEmpty(tool.getToolQcode()) || StringUtils.isEmpty(tool.getQcodeUrl())) {
        setTool(tool);
        update(tool);
      }
    }
    return list;
  }

  /**
   * 批量导出二维码
   */
  @Override
  public AjaxResult export(BaseSafetyTool safetyTool) {
    List<BaseSafetyTool> list = getList(safetyTool);
    return export(list);
  }

  /**
   * 查询列表
   */
  @Override
  public AjaxResult export(Long[] ids) {
    List<BaseSafetyTool> list = safetyToolMapper.getListByIds(ids);
    return export(list);
  }

  private AjaxResult export(List<BaseSafetyTool> tools){
    if(CollectionUtils.isEmpty(tools)){
      return AjaxResult.error("没查到要导出的记录");
    }
    // 如果只有一条，直接发图片
    if(tools.size() == 1){
      BaseSafetyTool tool = tools.get(0);
      String fileName = tool.getToolCode() + ".jpg";
      log.info("{} - {}", fileName, tool.getQcodeUrl());
      return AjaxResult.uploadFile(tool.getQcodeUrl(), fileName);
    }
    // 如果多条，打包压缩后发
    String tmpPath = localFilePath + "/qcode-" + DateUtils.dateTimeNow() + "/";
    File tmpFile = new File(tmpPath);
    if(!tmpFile.exists() && !tmpFile.mkdirs()){
      return AjaxResult.error("临时目录创建失败");
    }
    for (BaseSafetyTool tool : tools){
      File file = new File(tmpPath + tool.getToolCode() + ".jpg");
      byte[] byteArray = HttpUtils.sendGetStream(tool.getQcodeUrl());
      try (FileOutputStream os = new FileOutputStream(file, true)){
        os.write(byteArray, 0, byteArray.length);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    String zipFile;
    try {
      zipFile = ZipUtil.zipExportFiles(tmpPath, localFilePath);
    } catch (ZipException e) {
      return AjaxResult.error("文件压缩失败");
    }
    String zipFilePath = localFilePath + "/" + zipFile;
    log.info("压缩文件： {} - {}", zipFile, zipFilePath);
    return sysFileService.uploadFile(zipFilePath);
  }

  private void setTool(BaseSafetyTool tool){
    String qcode = tool.getToolQcode();
    if(StringUtils.isEmpty(qcode)) {
      qcode = snowflakeClient.code(QcodeEnum.LETTER_NUMBER) + "_"
          + tool.getToolType() + "_" + tool.getToolCode();
      tool.setToolQcode(qcode);
    }
    String dictType = "tool_type";
    String toolName = dictDataService.selectDictLabel(dictType, tool.getToolType());
    List<String> bottomDes = Arrays.asList(tool.getDeptName(), tool.getStorePlace(),
        toolName + " - " + tool.getToolCode());
    tool.setToolName(toolName);
    String filePath = FileUploadUtils.getAbsoluteFile(qcode + ".jpg");
    try {
      QrCodeUtil.encode(tool.getToolQcode(), bottomDes, filePath);
      String url = fileService.getUploadFileUrl(filePath);
      tool.setQcodeUrl(url);
    } catch (Exception ignored) {
    }
  }

  /**
   * 替换安全工具
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public int replaceTool(BaseSafetyTool baseSafetyTool) {
    Long toolId = baseSafetyTool.getToolId();
    //插入新的安全工具
    baseSafetyTool.setCreateTime(new Date());
    baseSafetyTool.setCreateBy(SecurityUtils.getUsername());
    baseSafetyTool.setState(ToolStateEnum.NORMAL.getCode());
    safetyToolMapper.insert(baseSafetyTool);

    //将原安全工具状态设置为报废并记录替换ID
    BaseSafetyTool temp = new BaseSafetyTool();
    temp.setToolId(toolId);
    temp.setScrapDate(new Date());
    temp.setState(ToolStateEnum.SCRAP.getCode());
    temp.setScrapUser(SecurityUtils.getUsername());
    temp.setReplaceToolId(baseSafetyTool.getToolId());

    return safetyToolMapper.update(temp);
  }

  /**
   * 刷新二维码
   */
  @Override
  public void refresh() {
    List<BaseSafetyTool> list = safetyToolMapper.getList(new BaseSafetyTool());
    for(BaseSafetyTool tool : list){
      if(StringUtils.isEmpty(tool.getToolQcode()) || StringUtils.isEmpty(tool.getQcodeUrl())) {
        setTool(tool);
        update(tool);
      }
    }
  }
}
