package com.qingyun.web.controller.api.contract;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Date;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qingyun.common.config.QingYunConfig;
import com.qingyun.common.exception.ServiceException;
import com.qingyun.common.helper.LoginHelper;
import com.qingyun.common.utils.DateUtils;
import com.qingyun.common.utils.MapstructUtils;
import com.qingyun.service.compare.service.ReviewTaskService;
import com.qingyun.service.domain.ContractReviewResult;
import com.qingyun.service.domain.ContractReviewTask;
import com.qingyun.service.domain.ContractRuleTemplate;
import com.qingyun.service.mapper.ContractReviewTaskMapper;
import com.qingyun.service.service.IContractRuleTemplateService;
import com.qingyun.service.service.impl.ContractReviewResultServiceImpl;
import com.qingyun.service.utils.PdfUtil;
import lombok.RequiredArgsConstructor;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.qingyun.idempotent.annotation.RepeatSubmit;
import com.qingyun.common.annotation.Log;
import com.qingyun.common.core.controller.BaseController;
import com.qingyun.common.core.domain.PageQuery;
import com.qingyun.common.core.domain.R;
import com.qingyun.common.core.validate.AddGroup;
import com.qingyun.common.core.validate.EditGroup;
import com.qingyun.common.enums.BusinessType;
import com.qingyun.service.domain.vo.ContractReviewTaskVo;
import com.qingyun.service.domain.bo.ContractReviewTaskBo;
import com.qingyun.service.service.IContractReviewTaskService;
import com.qingyun.mybatisplus.page.TableDataInfo;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;

/**
 * 合同审查任务
 *
 * @author jianlu
 * @date 2025-07-15
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/service/reviewTask")
public class ContractReviewTaskController extends BaseController {

    private final IContractReviewTaskService contractReviewTaskService;

    private final IContractRuleTemplateService contractRuleTemplateService;

    private final ReviewTaskService reviewTaskService;

    private final SqlSessionFactory sqlSessionFactory;

    private final PdfUtil pdfUtil;

    private final ContractReviewResultServiceImpl contractReviewResultService;

    /**
     * 查询审查任务列表 "service:reviewTask:list"
     */
    @SaCheckPermission("service:reviewTask:list")
    @GetMapping("/list")
    public TableDataInfo<ContractReviewTaskVo> list(ContractReviewTaskBo bo, PageQuery pageQuery) {
        return contractReviewTaskService.queryPageList(bo, pageQuery);
    }

    /**
     * 获取审查任务详细信息 "service:reviewTask:query"
     *
     * @param taskId 主键
     */
    @SaCheckPermission("service:reviewTask:query")
    @GetMapping("/{taskId}")
    public R<ContractReviewTaskVo> getInfo(@NotNull(message = "主键不能为空")
                                           @PathVariable Long taskId) {
        return R.ok(contractReviewTaskService.queryById(taskId));
    }

    /**
     * 新增审查任务 "service:reviewTask:add"
     */
    @SaCheckPermission("service:reviewTask:add")
    @Log(title = "审查任务", businessType = BusinessType.INSERT)
    //@RepeatSubmit(interval = 60000, message = "请稍候再试")
    @PostMapping("/create")
    public R<Integer> add(@Validated(AddGroup.class) @RequestBody ContractReviewTaskBo bo) {
        ContractReviewTask add = MapstructUtils.convert(bo, ContractReviewTask.class);
        if (add == null) {
            return R.fail("创建审查任务失败");
        }

        ContractRuleTemplate contractRuleTemplate = contractRuleTemplateService.getBaseMapper().selectById(bo.getTemplateId());
        if (contractRuleTemplate == null) {
            return R.fail("配置规则模板不存在");
        }
        add.setReviewRule(contractRuleTemplate.getReviewRuleJson());
        add.setReviewElement(contractRuleTemplate.getReviewElementJson());

        File pdfFile;
        File tempFile = null;
        try {
            // 临时文件
            tempFile = pdfUtil.downloadFile(add.getContractUrl(), add.getContractName());
            pdfFile = tempFile;
            String fileName = add.getContractName().toLowerCase();

            // 判断文件类型
            //如果是word类型转换成pdf
            if (fileName.endsWith(".doc") || fileName.endsWith(".docx")) {
                pdfFile = pdfUtil.convertWordToPdf(tempFile);
                // 在用户上传的word文件路径目录下创建新的pdf格式文件路径
                String needUploadName = DateUtils.datePath() + "/" + IdUtil.fastUUID() + "/" +
                    fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf";
                String filePath = QingYunConfig.getUploadPath() + "/" + needUploadName;

                // 确保目录存在
                File destFile = new File(filePath);
                destFile.getParentFile().mkdirs();

                // 将转换后的PDF文件移动到目标位置
                File targetFile = new File(filePath);
                if (pdfFile.renameTo(targetFile)) {
                    pdfFile = targetFile;
                } else {
                    // 如果renameTo失败，尝试复制文件
                    try (FileInputStream fis = new FileInputStream(pdfFile)) {
                        Files.copy(pdfFile.toPath(), targetFile.toPath());
                        pdfFile = targetFile;
                    }
                }
                // 更新合同URL为新的PDF文件路径
                add.setContractUrl("/profile/upload/" + needUploadName);
            }

            // 处理PDF文件
            PDDocument firstDocument = Loader.loadPDF(pdfFile);
            if (firstDocument == null) {
                throw new ServiceException("解析PDF文件失败");
            }
            add.setPageNum(firstDocument.getNumberOfPages());
            if (firstDocument.getNumberOfPages() > 0) {
                add.setWidth(firstDocument.getPage(0).getMediaBox().getWidth());
                add.setHeight(firstDocument.getPage(0).getMediaBox().getHeight());
            }
            firstDocument.close();
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceException("解析文件失败");
        } finally {
            try {
                if (tempFile != null  && tempFile.exists()) {
                    Files.deleteIfExists(tempFile.toPath());
                }
            } catch (IOException e) {
                log.error("删除文件失败", e);
            }
        }

        add.setUserId(LoginHelper.getUserId());
        add.setDeptId(LoginHelper.getDeptId());
        add.setStatus(2);  // 获取原文中
        add.setCreateBy(LoginHelper.getUsername());
        add.setCreateTime(new Date());

        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            ContractReviewTaskMapper mapper = sqlSession.getMapper(ContractReviewTaskMapper.class);
            mapper.insert(add);
            sqlSession.commit(); // 手动提交事务
        } catch (Exception e) {
            return R.fail("创建审查任务失败");
        }
        // 异步执行解析合同文档中
        contractReviewTaskService.execute(add, null);
        return R.ok("创建成功", 2);
    }


    /**
     * 执行审查任务 "service:reviewTask:execute"
     */
    @SaCheckPermission("service:reviewTask:execute")
    //@RepeatSubmit(interval = 60000, message = "任务正在执行中")
    @GetMapping("/execute/{taskId}")
    public R<Integer> execute(@PathVariable Long taskId) {
        BaseMapper<ContractReviewTask> baseMapper = contractReviewTaskService.getBaseMapper();
        ContractReviewTask contractReviewTask = baseMapper.selectById(taskId);
        if (contractReviewTask == null) {
            return R.fail("任务不存在");
        }
        if (contractReviewTask.getStatus() == 2) {
            return R.fail("任务正在执行中", 2);
        }
//        if (contractReviewTask.getStatus() != 0) {
//            return R.fail("任务还未准备好", contractReviewTask.getStatus());
//        }
        if (contractReviewTask.getTemplateId() == null && StringUtils.isBlank(contractReviewTask.getReviewRule())) {
            return R.fail("请先配置审查规则");
        }
        contractReviewTask.setStatus(2);
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            ContractReviewTaskMapper mapper = sqlSession.getMapper(ContractReviewTaskMapper.class);
            mapper.updateById(contractReviewTask);
            sqlSession.commit(); // 手动提交事务
        } catch (Exception e) {
            return R.fail("重试失败");
        }

        // 删除审查结果
        contractReviewResultService.getBaseMapper().delete(Wrappers.<ContractReviewResult>lambdaQuery().eq(ContractReviewResult::getTaskId, taskId));

        // 异步执行审查逻辑
        contractReviewTaskService.execute(contractReviewTask, contractReviewTask.getModelId());
        return R.ok(2);
    }

    /**
     * 重试 "service:reviewTask:retry"
     * @param taskId 任务ID
     */
    @SaCheckPermission("service:reviewTask:retry")
    @GetMapping("/retry/{taskId}")
    public R<Integer> retry(@PathVariable("taskId") Long taskId) {
        BaseMapper<ContractReviewTask> baseMapper = contractReviewTaskService.getBaseMapper();
        ContractReviewTask contractReviewTask = baseMapper.selectById(taskId);
        if (contractReviewTask == null) {
            return R.fail("任务不存在");
        }
        Integer status = contractReviewTask.getStatus();
        if (status == 1) {
            // 重试解析pdf页面
            reviewTaskService.parsePdf(contractReviewTask);
            return R.ok("重试成功", 1);
        } else {
            try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
                contractReviewTask.setStatus(2);
                ContractReviewTaskMapper mapper = sqlSession.getMapper(ContractReviewTaskMapper.class);
                mapper.updateById(contractReviewTask);
                sqlSession.commit(); // 手动提交事务
            } catch (Exception e) {
                return R.fail("重试失败");
            }
            // 删除审查结果
            contractReviewResultService.getBaseMapper().delete(Wrappers.<ContractReviewResult>lambdaQuery().eq(ContractReviewResult::getTaskId, taskId));
            // 重新执行任务
            contractReviewTaskService.execute(contractReviewTask, contractReviewTask.getModelId());
            return R.ok("重试成功", 2);
        }
    }

    /**
     * 获取审查任务状态 "service:reviewTask:status"
     */
    @SaCheckPermission("service:reviewTask:status")
    @GetMapping("/status/{taskId}")
    public R<Integer> status(@PathVariable("taskId") Long taskId) {
        BaseMapper<ContractReviewTask> baseMapper = contractReviewTaskService.getBaseMapper();
        ContractReviewTask contractReviewTask = baseMapper.selectById(taskId);
        if (contractReviewTask == null) {
            return R.fail("任务不存在");
        }
        return R.ok(contractReviewTask.getStatus());
    }

    /**
     * 修改审查任务 "service:reviewTask:edit"
     */
    @SaCheckPermission("service:reviewTask:edit")
    @Log(title = "审查任务", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PostMapping("/update")
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ContractReviewTaskBo bo) {
        return toAjax(contractReviewTaskService.updateByBo(bo));
    }

    /**
     * 删除审查任务 "service:reviewTask:remove"
     *
     * @param taskIds 主键串
     */
    @SaCheckPermission("service:reviewTask:remove")
    @Log(title = "审查任务", businessType = BusinessType.DELETE)
    @DeleteMapping("/{taskIds}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] taskIds) {
        return toAjax(contractReviewTaskService.deleteWithValidByIds(Arrays.asList(taskIds), Boolean.TRUE));
    }
}
