package com.engine.secret.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.secret.entity.unpack.CheckFields;
import com.engine.secret.entity.unpack.UnpackParam;
import com.engine.secret.exception.CustomizeRunTimeException;
import com.engine.secret.service.QualificationApplicationService;
import com.engine.secret.service.UnpackZipService;
import com.engine.secret.util.ConfigUtil;
import com.engine.secret.util.ModeUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wbi.util.Util;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.FileHeader;
import org.apache.commons.lang.StringUtils;
import weaver.docs.docs.DocImageManager;
import weaver.file.ImageFileManager;
import weaver.general.BaseBean;
import weaver.general.GCONST;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author:dxfeng
 * @createTime: 2024/08/29
 * @version: 1.0
 */
public class QualificationApplicationServiceImpl extends Service implements QualificationApplicationService {


    public static final String CONFIG_TABLE_NAME = "uf_config_package";
    public static final String CONFIG_DETAIL_TABLE_NAME = "uf_config_package_dt1";
    public static final String FILE_DETAIL_TABLE_NAME = "uf_config_package_dt2";

    BaseBean baseBean = new BaseBean();

    Map<String, FileHeader> fileHeaderMap;


    @Override
    public Map<String, Object> parsingFiles(Map<String, Object> param) {
        try {
            Map<String, Object> returnMap;

            String docId = Util.null2String(param.get("docId"));
            String requestId = Util.null2String(param.get("requestId"));
            String isCorrection = Util.null2String(param.get("isCorrection"));
            String checkFields = Util.null2String(param.get("checkFields"));
            if (StringUtils.isBlank(docId)) {
                throw new CustomizeRunTimeException("文件获取失败,请确认文件是否上传");
            }
            baseBean.writeLog("docId==" + docId);

            if (StringUtils.isBlank(requestId)) {
                throw new CustomizeRunTimeException("流程关联失败,未获取到流程ID,请保存后重试");
            }

            baseBean.writeLog("requestId==" + requestId);
            List<CheckFields> checkFieldsList = new ArrayList<>();
            if (StringUtils.isNotBlank(checkFields)) {
                checkFieldsList = JSON.parseObject(checkFields, new TypeReference<List<CheckFields>>() {});
            }

            UnpackParam unpackParam = UnpackParam.builder()
                    .docId(docId)
                    .requestId(requestId)
                    .isCorrection(Boolean.parseBoolean(isCorrection))
                    .checkFields(checkFieldsList)
                    .build();


            // docId 转为换imageFileId
            DocImageManager imgManger = new DocImageManager();
            imgManger.setDocid(Integer.parseInt(docId));
            imgManger.selectDocImageInfo();
            imgManger.next();
            String imageFileId = imgManger.getImagefileid();
            baseBean.writeLog("imageFileId==" + imageFileId);
            if (StringUtils.isBlank(imageFileId) || "-1".equals(imageFileId)) {
                throw new CustomizeRunTimeException("文件获取失败,请确认文件是否上传,imageFileId=[" + imageFileId + "]");
            }


            // 初始化配置
            String unzipPwd = ConfigUtil.getConfig("UNZIP_PWD");
            baseBean.writeLog("unzipPwd==" + unzipPwd);


            // 根据文件id获取文件流
            ImageFileManager manager = new ImageFileManager();
            manager.getImageFileInfoById(Integer.parseInt(imageFileId));
            manager.getImageFileName();
            InputStream inputStream = manager.getInputStream();

            Path fixedDir = Paths.get(GCONST.getRootPath() + "filesystem" + File.separatorChar + "downloadBatchTemp");
            Files.createDirectories(fixedDir);
            Path tempZipFile = Files.createTempFile(fixedDir, "offline_temp_", ".zip");
            baseBean.writeLog("tempZipFile==" + tempZipFile.toString());
            Files.copy(inputStream, tempZipFile, StandardCopyOption.REPLACE_EXISTING);

            //解压文件，处理压缩包
            baseBean.writeLog("开始解压文件，处理压缩包");
            returnMap = unzipWithPassword(tempZipFile, Paths.get("output"), unzipPwd, unpackParam);
            baseBean.writeLog("压缩包处理完成");
            return returnMap;
        } catch (Exception e) {
            baseBean.writeLog(e);
            throw new CustomizeRunTimeException(e.getMessage(), e);
        }
    }

    @Override
    public Map<String, Object> deleteParsedData(Map<String, Object> param) {

        UnpackZipService unpackZipService = ServiceUtil.getService(OfflineZipUnpackServiceImpl.class, user);
        return unpackZipService.deleteParsedData(param);
    }

    /**
     * 解压ZIP文件
     *
     * @param zipFilePath
     * @param outputDir
     * @param password
     */
    private Map<String, Object> unzipWithPassword(Path zipFilePath, Path outputDir, String password, UnpackParam unpackParam) {
        try {
            ZipFile zipFile = new ZipFile(zipFilePath.toFile());
            if (zipFile.isEncrypted()) {
                zipFile.setPassword(password.toCharArray());
            }
            // 遍历并解压所有文件
            zipFile.extractAll(outputDir.toString());
            baseBean.writeLog("已解压所有文件");

            // 遍历 ZIP 内文件（可选）
            List<FileHeader> fileHeaders = zipFile.getFileHeaders();

            //imageFileMap = new HashMap<>();
            fileHeaderMap = new HashMap<>();
            for (FileHeader header : fileHeaders) {
                if (header.isDirectory()) {
                    continue;
                }
                String fullPath = header.getFileName();
                int lastSlashIndex = fullPath.lastIndexOf('/');
                String fileName = (lastSlashIndex != -1)
                        ? fullPath.substring(lastSlashIndex + 1)
                        : fullPath;
                fileHeaderMap.put(fileName, header);
            }


            baseBean.writeLog("fileHeaders.size==" + fileHeaders.size());
            baseBean.writeLog("fileHeaderMap.size==" + fileHeaderMap.size());
            baseBean.writeLog("fileHeaderMap==" + JSON.toJSONString(fileHeaderMap));


            // 获取数据文件，用于后续数据解析
            String jsonFileName = "(database)data.json";
            if (unpackParam.isCorrection()) {
                jsonFileName = "(extra)data.json";
            }
            FileHeader fileHeader = fileHeaderMap.get(jsonFileName);
            int dataJsonImageId = generateImageFileId(zipFile, fileHeader, jsonFileName);

            if (dataJsonImageId > 0) {
                // 离线端方式
                JsonNode rootNode = parseJsonContent(dataJsonImageId);
                OfflineZipUnpackServiceImpl offlineZipUnpackService = ServiceUtil.getService(OfflineZipUnpackServiceImpl.class, user);
                if (unpackParam.isCorrection()) {
                    return offlineZipUnpackService.reviewResubmittedMaterials(zipFile, unpackParam.getRequestId(), rootNode, fileHeaderMap);
                }
                return offlineZipUnpackService.registerAcceptance(zipFile, unpackParam, rootNode, fileHeaderMap);
            }

            // TODO 兼容其他方式

            return new HashMap<>();

        } catch (Exception e) {
            if (e.getMessage().contains("Wrong password")) {
                throw new CustomizeRunTimeException("数据包解压失败,密码错误");
            } else {
                baseBean.writeLog(e);
                throw new CustomizeRunTimeException(e.getMessage(), e);
            }
        } finally {
            try {
                Files.deleteIfExists(zipFilePath);
            } catch (IOException e) {
                baseBean.writeLog(e);
            }
        }
    }


    /**
     * 获取JSON文件内容
     *
     * @param imageFieldId
     * @return
     * @throws IOException
     */
    private static JsonNode parseJsonContent(Integer imageFieldId) throws IOException {
        ImageFileManager manager = new ImageFileManager();
        manager.getImageFileInfoById(imageFieldId);
        InputStream inputStream = manager.getInputStream();
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readTree(inputStream);
    }

    /**
     * 上传文件 返回imageFileId
     *
     * @param zipFile
     * @param header
     * @return
     */
    private int generateImageFileId(ZipFile zipFile, FileHeader header, String fileName) {
        try (InputStream is = zipFile.getInputStream(header)) {
            return ModeUtil.generateImageFileId(is, fileName);
        } catch (Exception e) {
            throw new CustomizeRunTimeException(e);
        }
    }

}
