package com.zt.plat.module.base.controller.admin.templtp.onlyoffice.service;

import com.alibaba.fastjson2.JSONObject;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.module.base.controller.admin.templtp.onlyoffice.pojo.Action;
import com.zt.plat.module.base.controller.admin.templtp.onlyoffice.pojo.History;
import com.zt.plat.module.base.controller.admin.templtp.onlyoffice.pojo.OnlyOfficeCallback;
import com.zt.plat.module.base.dal.dataobject.tmpltp.TmplInscBsnRelDO;
import com.zt.plat.module.base.dal.mysql.tmpltp.TmplInscBsnRelMapper;
import com.zt.plat.module.base.service.tmpltp.TemplateInstanceService;
import com.zt.plat.module.infra.api.file.FileApi;
import com.zt.plat.module.infra.api.file.dto.FileCreateReqDTO;
import com.zt.plat.module.infra.api.file.dto.FileRespDTO;
import com.zt.plat.module.system.api.dept.DeptApi;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.zt.plat.module.base.controller.admin.templtp.onlyoffice.util.UrlFileDownloader.downloadFileAsMultipart;


@Service
@RequiredArgsConstructor
@Slf4j
public class OnlyOfficeCallbackServiceImpl implements OnlyOfficeCallbackService {
    private final FileApi fileApi;
    private final TemplateInstanceService templateInstanceService;
    private final TmplInscBsnRelMapper tmplInscBsnRelMapper;
    @Override
    public void processCallback(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("收到OnlyOffice文档回调: {}", callback.getKey());
        log.info("回调状态: {}", callback.getStatus());

        // 根据不同的状态处理回调
        switch (callback.getStatus()) {
            case 1:
                handleEditingStatus(callback, id,fileName);
                break;
            case 2:
                handleDocumentSaved(callback, id,fileName);
                break;
            case 3:
                handleSaveError(callback, id,fileName);
                break;
            case 4:
                handleDocumentClosedWithoutChanges(callback, id,fileName);
                break;
            case 6:
                handleForcedSave(callback, id,fileName);
                break;
            case 7:
                handleForcedSaveError(callback, id,fileName);
                break;
            default:
                log.warn("收到未知的回调状态: {}", callback.getStatus());
        }
    }

    /**
     * 处理文档正在编辑的状态
     */
    private void handleEditingStatus(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 正在被以下用户编辑: {}",
                callback.getKey(), callback.getUsers());

        // 处理用户操作（连接或断开连接）
        if (callback.getActions() != null) {
            for (Action action : callback.getActions()) {
                String actionType = switch (action.getType()) {
                    case 0 -> "断开了连接";
                    case 1 -> "连接成功";
                    case 2 -> "在中点击了强制保存";
                    default -> "在中执行了未知操作";
                };
                log.info("用户 {} {}", action.getUserId(), actionType);
            }
        }
    }

    /**
     * 处理文档已保存的状态
     */
    private void handleDocumentSaved(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 已准备好保存", callback.getKey());
        saveDocument(callback, id,fileName);

        // 处理历史记录
        // handleHistoryChanges(callback,id);
    }

    /**
     * 处理保存错误的状态
     */
    private void handleSaveError(OnlyOfficeCallback callback, String id,String fileName) {
        log.error("保存文档 {} 时出错", callback.getKey());
        // 可以在这里添加错误处理逻辑，如发送通知等
    }

    /**
     * 处理文档关闭且无更改的状态
     */
    private void handleDocumentClosedWithoutChanges(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 已关闭，未做任何更改", callback.getKey());
        // 可以在这里添加清理资源等逻辑
    }

    /**
     * 处理强制保存的状态
     */
    private void handleForcedSave(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 执行强制保存。类型: {}",
                callback.getKey(), callback.getForceSaveType());
        saveDocument(callback, id,fileName);

        // 处理历史记录
        handleHistoryChanges(callback, id);

        // 如果是表单提交，处理表单数据
        if (callback.getForceSaveType() == 3 && callback.getFormsDataUrl() != null) {
            handleFormSubmission(callback, id);
        }
    }

    /**
     * 处理强制保存错误的状态
     */
    private void handleForcedSaveError(OnlyOfficeCallback callback, String id,String fileName) {
        log.error("文档 {} 强制保存时出错", callback.getKey());
        // 可以在这里添加错误处理逻辑
    }

    /**
     * 保存文档到存储
     */
    private void saveDocument(OnlyOfficeCallback callback, String id,String fileName) {
        if (callback.getUrl() == null) {
            log.error("文件路径为空");
            return;
        }

        try {
            MultipartFile file = downloadFileAsMultipart(callback.getUrl());
            // 1. 验证文件是否为空

            String directory = "模版实例";
            FileCreateReqDTO fileCreateReqDTO = new FileCreateReqDTO();
            fileCreateReqDTO.setName(fileName);
            fileCreateReqDTO.setContent(file.getBytes());
            fileCreateReqDTO.setType(file.getContentType()); // 使用真实的MIME类型
            fileCreateReqDTO.setDirectory(directory); // 设置文件存储目录
            if (file.getSize() <=0){
                log.error("文件大小为0");
                return;
            }
            // 7. 调用文件服务创建文件
            CommonResult<FileRespDTO> result = fileApi.createFileWithReturn(fileCreateReqDTO);
            if (result.isSuccess()) {
                // 创建文件成功，处理结果
                result.getData().setContent(null);
                log.info("文件创建成功，文件ID：{}", result.getData());
                // 创建文件成功，处理结果
                FileRespDTO fileRespDTO = result.getData();
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("id",String.valueOf(fileRespDTO.getId()));
                fileInfo.put("name", fileRespDTO.getName());
                fileInfo.put("directory", fileRespDTO.getDirectory());
                fileInfo.put("key", callback.getKey());
                templateInstanceService.updateTemplateInstanceFileUrlByInstanceId(id, JSONObject.toJSONString(fileInfo));
            } else {
                // 创建文件失败，处理错误
                log.error("文件创建失败，错误信息：{}", result.getMsg());
            }
            log.info("文件创建结果：{}", result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 处理文档历史记录变更
     */
    private void handleHistoryChanges(OnlyOfficeCallback callback, String id) {
        History history = callback.getHistory();
        if (history != null) {
            log.info("正在处理文档 {} 的历史记录变更", callback.getKey());
            // 这里可以实现处理历史记录的逻辑
            // 例如：调用refreshHistory方法更新历史记录
        }

        // 处理变更历史URL
        if (callback.getChangesUrl() != null) {
            log.info("文档 {} 的变更历史URL: {}", callback.getKey(), callback.getChangesUrl());
            // 这里可以实现保存变更历史的逻辑
            // 例如：下载变更历史并使用setHistoryData方法存储
        }
    }

    /**
     * 处理表单提交数据
     */
    private void handleFormSubmission(OnlyOfficeCallback callback, String id) {
        log.info("正在处理文档 {} 的表单提交", callback.getKey());
        // 这里可以实现处理表单数据的逻辑
        // 例如：从formsDataUrl下载并解析表单数据
    }





    @Override
    public void processContractCallback(OnlyOfficeCallback callback, String id, String fileName) {
        log.info("收到OnlyOffice文档回调: {}", callback.getKey());
        log.info("回调状态: {}", callback.getStatus());

        // 根据不同的状态处理回调
        switch (callback.getStatus()) {
            case 1:
                handleContractEditingStatus(callback, id,fileName);
                break;
            case 2:
                handleContractDocumentSaved(callback, id,fileName);
                break;
            case 3:
                handleContractSaveError(callback, id,fileName);
                break;
            case 4:
                handleContractDocumentClosedWithoutChanges(callback, id,fileName);
                break;
            case 6:
                handleContractForcedSave(callback, id,fileName);
                break;
            case 7:
                handleContractForcedSaveError(callback, id,fileName);
                break;
            default:
                log.warn("收到未知的回调状态: {}", callback.getStatus());
        }
    }


    /**
     * 处理文档正在编辑的状态
     */
    private void handleContractEditingStatus(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 正在被以下用户编辑: {}",
                callback.getKey(), callback.getUsers());

        // 处理用户操作（连接或断开连接）
        if (callback.getActions() != null) {
            for (Action action : callback.getActions()) {
                String actionType = switch (action.getType()) {
                    case 0 -> "断开了连接";
                    case 1 -> "连接成功";
                    case 2 -> "在中点击了强制保存";
                    default -> "在中执行了未知操作";
                };
                log.info("用户 {} {}", action.getUserId(), actionType);
            }
        }
    }

    /**
     * 处理文档已保存的状态
     */
    private void handleContractDocumentSaved(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 已准备好保存", callback.getKey());
        saveContractDocument(callback, id,fileName);

        // 处理历史记录
        // handleHistoryChanges(callback,id);
    }

    /**
     * 处理保存错误的状态
     */
    private void handleContractSaveError(OnlyOfficeCallback callback, String id,String fileName) {
        log.error("保存文档 {} 时出错", callback.getKey());
        // 可以在这里添加错误处理逻辑，如发送通知等
    }

    /**
     * 处理文档关闭且无更改的状态
     */
    private void handleContractDocumentClosedWithoutChanges(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 已关闭，未做任何更改", callback.getKey());
        // 可以在这里添加清理资源等逻辑
    }

    /**
     * 处理强制保存的状态
     */
    private void handleContractForcedSave(OnlyOfficeCallback callback, String id,String fileName) {
        log.info("文档 {} 执行强制保存。类型: {}",
                callback.getKey(), callback.getForceSaveType());
        saveContractDocument(callback, id,fileName);

        // 处理历史记录
        handleHistoryChanges(callback, id);

        // 如果是表单提交，处理表单数据
        if (callback.getForceSaveType() == 3 && callback.getFormsDataUrl() != null) {
            handleFormSubmission(callback, id);
        }
    }


    /**
     * 处理强制保存错误的状态
     */
    private void handleContractForcedSaveError(OnlyOfficeCallback callback, String id,String fileName) {
        log.error("文档 {} 强制保存时出错", callback.getKey());
        // 可以在这里添加错误处理逻辑
    }

    /**
     * 保存文档到存储
     */
    private void saveContractDocument(OnlyOfficeCallback callback, String id,String fileName) {
        if (callback.getUrl() == null) {
            log.error("文件路径为空");
            return;
        }

        try {
            MultipartFile file = downloadFileAsMultipart(callback.getUrl());
            // 1. 验证文件是否为空

            String directory = "模版实例";
            FileCreateReqDTO fileCreateReqDTO = new FileCreateReqDTO();
            fileCreateReqDTO.setName(fileName);
            fileCreateReqDTO.setContent(file.getBytes());
            fileCreateReqDTO.setType(file.getContentType()); // 使用真实的MIME类型
            fileCreateReqDTO.setDirectory(directory); // 设置文件存储目录
            if (file.getSize() <=0){
                log.error("文件大小为0");
                return;
            }
            // 7. 调用文件服务创建文件
            CommonResult<FileRespDTO> result = fileApi.createFileWithReturn(fileCreateReqDTO);
            if (result.isSuccess()) {
                // 创建文件成功，处理结果
                result.getData().setContent(null);
                log.info("文件创建成功，文件ID：{}", result.getData());
                // 创建文件成功，处理结果
                FileRespDTO fileRespDTO = result.getData();
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("id",String.valueOf(fileRespDTO.getId()));
                fileInfo.put("name", fileRespDTO.getName());
                fileInfo.put("directory", fileRespDTO.getDirectory());
                fileInfo.put("key", callback.getKey());
                TmplInscBsnRelDO createReqVO = new TmplInscBsnRelDO();
                createReqVO.setId(Long.valueOf(id));
                createReqVO.setCntt(JSONObject.toJSONString(fileInfo));
                tmplInscBsnRelMapper.updateById(createReqVO);
            } else {
                // 创建文件失败，处理错误
                log.error("文件创建失败，错误信息：{}", result.getMsg());
            }
            log.info("文件创建结果：{}", result);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}
