/*
* Copyright (c) 京北方信息技术股份有限公司 Corporation 2022 . All rights reserved.
*
*/
package net.northking.cctp.scriptcase.api.atuscriptrecord.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.northking.cctp.common.enums.FileBusinessTypeEnum;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.common.http.ResultWrapper;
import net.northking.cctp.common.s3.FileUploadException;
import net.northking.cctp.common.s3.NKFile;
import net.northking.cctp.common.s3.SimpleStorageService;
import net.northking.cctp.common.security.authentication.NKSecurityContext;
import net.northking.cctp.scriptcase.api.scenescript.bean.Node;
import net.northking.cctp.scriptcase.api.scenescript.bean.SceneScript;
import net.northking.cctp.scriptcase.api.scenescript.service.coordinate.SceneCoordinatorService;
import net.northking.cctp.scriptcase.constants.ScriptConstant;
import net.northking.cctp.scriptcase.db.entity.AtuSceneInfo;
import net.northking.cctp.scriptcase.db.entity.AtuScriptInfo;
import net.northking.cctp.scriptcase.db.service.AtuSceneInfoService;
import net.northking.cctp.scriptcase.db.service.AtuScriptInfoService;
import net.northking.cctp.scriptcase.dto.atuscriptrecord.ScriptInputTableDto;
import net.northking.cctp.scriptcase.dto.casedesign.TableHeader;
import net.northking.cctp.scriptcase.enums.ScriptCaseAppError;
import net.northking.cctp.scriptcase.tools.DownloadFileUtils;
import net.northking.cctp.scriptcase.tools.MinioPathUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据源配置服务实现类
 *
 * @author maven-cctp-plugin
 * @since 1.0
 */

@Service
@ConditionalOnMissingBean(name = "AtuInputApiServiceImpl")
public class AtuInputApiServiceImpl implements AtuInputApiService
{
  /**
   * 日志
   */
  private final static Logger logger = LoggerFactory.getLogger(AtuInputApiServiceImpl.class);


  @Autowired
  private SimpleStorageService simpleStorageService;

  @Autowired
  private AtuScriptInfoService atuScriptInfoService;

  @Autowired
  private AtuSceneInfoService atuSceneInfoService;

  @Autowired
  private SceneCoordinatorService sceneCoordinatorService;

  @Autowired
  private MinioPathUtils pathUtil;

  @Autowired
  private DownloadFileUtils downloadFileUtils;

  @Override
  public void downloadTemplate(HttpServletResponse response,HttpServletRequest request, String templateParam) {
      try {
        XSSFWorkbook hssfWorkbook = getXSSFWorkbook(templateParam.split(","), null);
        setResponseHeader(response,request);
        ServletOutputStream outputStream = response.getOutputStream();
        hssfWorkbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
      }catch (IOException e){
        logger.error(e.getMessage());
      }
  }

  public XSSFWorkbook getXSSFWorkbook (String title[], XSSFWorkbook workbook){
    if (null==workbook){
      workbook=new XSSFWorkbook();
    }
    XSSFSheet sheet1 = workbook.createSheet(ScriptConstant.INPUT_SET_IMPORT_MODULE);
    XSSFRow row = sheet1.createRow(0);
    XSSFCellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setAlignment(HorizontalAlignment.CENTER);
    XSSFCell cell=null;
    for (int i=0;i<title.length;i++){
      cell = row.createCell(i);
      cell.setCellValue(title[i]);
      cell.setCellStyle(cellStyle);
    }
    return workbook;
  }

  public void setResponseHeader(HttpServletResponse response, HttpServletRequest request)  {
    try {
      String fileName=ScriptConstant.INPUT_SET_IMPORT_MODULE;
      fileName= URLEncoder.encode(fileName,ScriptConstant.UTF);
      response.reset();
      response.setCharacterEncoding(ScriptConstant.STR_ENCODE);
      response.setContentType(ScriptConstant.APPLICATION_CHARSET);
      response.setHeader(ScriptConstant.CONTENT_DISPOSITION, ScriptConstant.FILE_NAME + fileName + ScriptConstant.FILE_XLSX);
    }catch (Exception e){
      logger.error(e.getMessage());
    }
  }


  @Override
  public ResultWrapper importExcel(MultipartFile file, List<TableHeader> tableHeaders, Integer type, String scriptId, String path) {//只支持xls
    ResultWrapper<JSONObject> wrapper=new ResultWrapper<>();
    if (file.isEmpty()){
      throw new PlatformRuntimeException(ScriptCaseAppError.FILE_IS_NULL);
    }
    String name = file.getOriginalFilename();
    String substring = name.substring(name.lastIndexOf("."));
    //xls->hssf,xlsx-xssf;
    if (".xls".equals(substring)){
      //获取excel实例
      HSSFWorkbook sheets = null;
      try {
        sheets = new HSSFWorkbook(file.getInputStream());
      } catch (IOException e) {
        logger.error("",e);
        logger.error("------输入项导入--------:"+e.getMessage());
        throw new PlatformRuntimeException(ScriptCaseAppError.EXCEL_FILE_READ_ERROR);
      }
      //获取sheet
      HSSFSheet sheet = sheets.getSheetAt(0);
      //获取表头信息
      HSSFRow rowHeader = sheet.getRow(0);
      //获取列数
      int rows = rowHeader.getPhysicalNumberOfCells();
      if (rows!=tableHeaders.size()) {
        throw new PlatformRuntimeException(ScriptCaseAppError.TABLE_HEADER_SIZE_ERROR);
      }
      //拼表头信息为字符串
      ArrayList<String> sb = new ArrayList<>();
      ArrayList<String> sbh = new ArrayList<>();
      for (int i=0;i<rows;i++){
        sb.add(rowHeader.getCell(i).getStringCellValue());
        sbh.add(tableHeaders.get(i).getName());
      }
      //判断导入文件中的表头字段跟前端界面显示是否一致
      if (!CollectionUtils.isEqualCollection(sb,sbh)){
        throw new PlatformRuntimeException(ScriptCaseAppError.TABLE_HEADER_NAME_HAS_ERROR);
      }
      //解析excel文件内容
      JSONObject jsonObject = new JSONObject();
      List<Map<String,Object>> tableContents=new ArrayList<>();
      Map<String ,Object> map=null;
      //从第二行开始
      for (int i=1;i<sheet.getPhysicalNumberOfRows();i++) {
        map=new HashMap<>();
        HSSFRow row = sheet.getRow(i);
        for (int j = 0; j < rows; j++) {
          HSSFCell cell = row.getCell(j);
          if (cell.getCellType()==CellType.NUMERIC){
            if (DateUtil.isCellDateFormatted(cell)){
              SimpleDateFormat sdf=new SimpleDateFormat(ScriptConstant.SIMPLE_FORMAT);
              map.put(tableHeaders.get(j).getName(),sdf.format(cell.getDateCellValue()));
            }else {
              map.put(tableHeaders.get(j).getName(), cell.getNumericCellValue());
            }
          }else {
          cell.setCellType(CellType.STRING);
          map.put(tableHeaders.get(j).getName(), cell.getStringCellValue());
          }
        }
        tableContents.add(map);
      }
      jsonObject.put(ScriptConstant.SCRIPT_INPUT_TABLE_CONTENT,tableContents);
      return wrapper.success(jsonObject);
    }else if (ScriptConstant.FILE_XLSX.equals(substring)){
      //获取excel实例
      XSSFWorkbook sheets = null;
      try {
        sheets = new XSSFWorkbook(file.getInputStream());
      } catch (IOException e) {
        logger.error("",e);
        logger.error("------输入项导入--------:"+e.getMessage());
        throw new PlatformRuntimeException(ScriptCaseAppError.EXCEL_FILE_READ_ERROR);
      }
      //获取sheet
      XSSFSheet sheet = sheets.getSheetAt(0);
      //获取表头信息
      XSSFRow rowHeader = sheet.getRow(0);
      //获取列数
      int rows = rowHeader.getPhysicalNumberOfCells();
      if (rows!=tableHeaders.size()){
        throw new PlatformRuntimeException(ScriptCaseAppError.TABLE_HEADER_SIZE_ERROR);
      }
      //拼表头信息为字符串
      ArrayList<String> sb = new ArrayList<>();
      ArrayList<String> sbh = new ArrayList<>();
      for (int i=0;i<rows;i++){
        sb.add(rowHeader.getCell(i).getStringCellValue());
        sbh.add(tableHeaders.get(i).getName());
      }
      //判断导入文件中的表头字段跟前端界面显示是否一致
      if (!CollectionUtils.isEqualCollection(sb,sbh)){
        throw new PlatformRuntimeException(ScriptCaseAppError.TABLE_HEADER_NAME_HAS_ERROR);
      }
      //解析excel文件内容
      JSONObject jsonObject = new JSONObject();
      List<Map<String,Object>> tableContents=new ArrayList<>();
      Map<String ,Object> map=null;
      //从第二行开始
      for (int i=1;i<sheet.getPhysicalNumberOfRows();i++) {
        map=new HashMap<>();
        XSSFRow row = sheet.getRow(i);
        for (int j = 0; j < rows; j++) {
          XSSFCell cell = row.getCell(j);
          if (cell.getCellType()==CellType.NUMERIC){
            if (DateUtil.isCellDateFormatted(cell)){
              SimpleDateFormat sdf=new SimpleDateFormat(ScriptConstant.SIMPLE_FORMAT);
              map.put(tableHeaders.get(j).getName(),sdf.format(cell.getDateCellValue()));
            }else {
              map.put(tableHeaders.get(j).getName(), cell.getNumericCellValue());
            }
          }else {
          cell.setCellType(CellType.STRING);
          map.put(tableHeaders.get(j).getName(), cell.getStringCellValue());
          }
        }
        tableContents.add(map);
      }
      jsonObject.put(ScriptConstant.SCRIPT_INPUT_TABLE_CONTENT,tableContents);
      return wrapper.success(jsonObject);
    }
    return wrapper;
  }


  private String insertToMinio(JSONObject object, String objId, FileBusinessTypeEnum businessCode) {
    File nkFile = MinioPathUtils.objectToJsonFile(object);
    NKFile upload = null;
    try {
      upload = simpleStorageService.upload(NKSecurityContext.getTenantId(), nkFile, objId, businessCode);
    } catch (FileUploadException e) {
      logger.error("",e);
    }
    String result = null;
    if (upload != null) {
      result = MinioPathUtils.pathToId(NKSecurityContext.getTenantId(), upload.getId());
    }
    return result;
  }

  @Override
  public JSONObject find(String path) {
    //下载场景脚本
    JSONObject jsonObject = downloadFileUtils.downloadScriptFile(path);
    SceneScript sceneScript = JSON.parseObject(JSON.toJSONString(jsonObject), SceneScript.class);
    if (sceneScript == null) {
      throw new PlatformRuntimeException(ScriptCaseAppError.SCENE_DATA_CHANGE_ERROR);
    }
    //场景脚本开始节点
    List<Node> listNodes = sceneScript.getNodes();
    for (Node curNode : listNodes) {
      if (!curNode.getNodeType().equals(ScriptConstant.START) && !curNode.getNodeType().equals(ScriptConstant.END)) {
        sceneCoordinatorService.refreshNodeScriptInfo(curNode);
      }
    }
    //封装反显对象
    jsonObject.put(ScriptConstant.NODES, listNodes);
    return jsonObject;
  }

  @Override
  public JSONObject findByScriptId(String scriptId) {
    AtuScriptInfo byPrimaryKey = atuScriptInfoService.findByPrimaryKey(scriptId);
    if (null!=byPrimaryKey&&null!=byPrimaryKey.getDataUrl()&&!"".equals(byPrimaryKey.getDataUrl())) {
      JSONObject jsonObject = downloadFileUtils.downloadScriptFile(byPrimaryKey.getDataUrl());
      //封装反显对象
      return jsonObject;
    }else
      return null;
  }

  @Override
  public JSONObject findBySceneId(String sceneId) {
    AtuSceneInfo byPrimaryKey = atuSceneInfoService.findByPrimaryKey(sceneId);
    if (null!=byPrimaryKey&&null!=byPrimaryKey.getDataUrl()&&!"".equals(byPrimaryKey.getDataUrl())) {
      JSONObject jsonObject = downloadFileUtils.downloadScriptFile(byPrimaryKey.getDataUrl());
      //封装反显对象
      return jsonObject;
    }else
      return null;
  }

  @Override
  public String saveSceneScriptData(ScriptInputTableDto dto) {
    StringBuilder path = new StringBuilder();
    path.append(generateScriptFileAndUpload(dto, dto.getScriptId(), FileBusinessTypeEnum.SCENE_SCRIPT_INPUT_DATA_SET));
    String scriptId = dto.getScriptId();
    //编辑已有脚本
    if (StringUtils.hasText(scriptId)) {
      //更新脚本数据
      AtuSceneInfo byPrimaryKey = atuSceneInfoService.findByPrimaryKey(scriptId);
      if (null != byPrimaryKey && byPrimaryKey.getIsDeleted().equals(0)) {
        AtuSceneInfo scriptInfo = new AtuSceneInfo();
        BeanUtils.copyProperties(byPrimaryKey, scriptInfo);
        scriptInfo.setDataUrl(path.toString());
        atuSceneInfoService.updateByPrimaryKey(scriptInfo);
      }
    }
    return path.toString();
  }


  /**
   * 生成脚本文件并上传
   * @param scriptJsonStr
   * @return
   */
  private String generateScriptFileAndUpload(Object scriptJsonStr, String objId, FileBusinessTypeEnum businessCode) {
    File file = pathUtil.objectToJsonFile(scriptJsonStr);
    try {
      NKFile nkFile = simpleStorageService.upload(NKSecurityContext.getTenantId(), file, objId, businessCode);
      String path = pathUtil.pathToId(NKSecurityContext.getTenantId(), nkFile.getId());
      return path;
    } catch (FileUploadException e) {
      logger.error("上传脚本文件出错", e);
    } finally {
      boolean delete = file.delete();
      if (!delete) {
        logger.error("删除文件失败");
      }
    }
    return null;
  }



}
