package org.jk.rag.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jk.common.mybatis.core.page.PageQuery;
import org.jk.rag.domain.dto.JkDialogReqDTO;
import org.jk.rag.domain.dto.JkDialogRespDTO;
import org.jk.rag.domain.dto.JkQuestionDTO;
import org.jk.rag.domain.entity.*;
import org.jk.rag.service.IJkRagService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jk.common.core.domain.R;
import org.jk.common.core.domain.model.LoginUser;
import org.jk.common.core.domain.model.TreeStruct;
import org.jk.common.core.enums.ProjectTypeEnum;
import org.jk.common.core.exception.ServiceException;
import org.jk.common.excel.utils.ExcelUtil;
import org.jk.common.log.enums.BusinessType;
import org.jk.common.mybatis.core.page.TableDataInfo;
import org.jk.common.satoken.utils.LoginHelper;
import org.jk.common.web.core.BaseController;
import org.jk.common.log.annotation.Log;
import org.jk.system.domain.SysProject;
import org.jk.system.domain.bo.SysDictDataBo;
import org.jk.system.domain.vo.SysDictDataVo;
import org.jk.system.service.ISysDictDataService;
import org.jk.system.service.ISysPermissionService;
import org.jk.system.service.ISysProjectService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/deepseek/api")
public class JkRagController extends BaseController {


    private final IJkRagService iJkRagService;

    private final ISysDictDataService dictDataService;

    private final ISysPermissionService permissionService;

    private final ISysProjectService sysProjectService;

    /**
     * 对话聊天
     *
     * @param response
     * @param request
     * @param sseParams
     * @return
     */
    @PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter chat(HttpServletResponse response, HttpServletRequest request, @RequestBody JkSseInfoParams sseParams)
            throws Exception {
        return iJkRagService.sseInvoke(sseParams);
    }

    /**
     * 预调试对话聊天
     *
     * @param response
     * @param request
     * @param params
     * @return
     */
    @PostMapping(value = "/preChat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter preChat(HttpServletResponse response, HttpServletRequest request, @RequestBody JkPreviewSeeParams params)
        throws Exception {
        return iJkRagService.previewSseInvoke(params);
    }

    @PostMapping("/async/completions")
    public R<List> asyncCompletions(@RequestBody JkCompletionsParams params) {
        return R.ok(iJkRagService.asyncCompletions(params));
    }

    @PostMapping("/free/async/completions")
    public R<List> freeAsyncCompletions(@RequestBody JkCompletionsParams params) {
        return asyncCompletions(params);
    }


    /**
     * 首页
     *
     * @param params
     * @return
     */
    @PostMapping("/index")
    public R<Map<String, Object>> index(@RequestBody PageParams params) {
        JkApplication vo = setFlagParams(params.getUserId(), params.getTypeId(), params.getProjectId(), 2);
        // 问答应用总数
        List<JkApplicationResult> appList = iJkRagService.getApplicationList(vo);
        // 知识库总数
        List<JkKnowledge> knowledgeList = iJkRagService.queryKnowledgeList();
        Map<String, Object> map = new HashMap();
        map.put("applicationCount", appList.size());
        map.put("knowledgeCount", knowledgeList.size());
        return R.ok(map);
    }

    /**
     * 获取聊天列表
     *
     * @param params
     * @return
     */
    @PostMapping("/chatHistory/list")
    public TableDataInfo dataExportList(@RequestBody JkPageParams params,@RequestBody PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        String userId = null;
        boolean isAdmin = false;
        if (loginUser != null) {
            isAdmin = LoginHelper.isTenantAdmin();
        }
        if(isAdmin) {
            userId = null;
        } else {
            userId = params.getUserId() == null ? userId : params.getUserId();
        }
        if (StringUtils.isNotBlank(params.getAppId())) {
            //获取应用聊天列表
            //PageHelper.startPage(params.getPageNumber(), params.getPageSize(), "").setReasonable(true);
            Page<JkDialogRespDTO> list = iJkRagService.selectDialogPageListByAppId(params.getAppId(), userId,pageQuery);
            List<Object> result = iJkRagService.setDialogList(list.getRecords());
            Page<JkDialogRespDTO> page = (Page<JkDialogRespDTO>) list;
            return TableDataInfo.build(result);
        } else {
            //获取所有列表
            //PageHelper.startPage(params.getPageNumber(), params.getPageSize(), "").setReasonable(true);
            List<JkDialogRespDTO> list = iJkRagService.selectDialogListByAppId(null, userId);
            List<Object> result = iJkRagService.setDialogList(list);
            Page<JkDialogRespDTO> page = (Page<JkDialogRespDTO>) list;
            return TableDataInfo.build(result);
        }
    }


    /**
     * 导出聊天记录
     *
     * @param response
     * @param id
     */
    @Log(title = "聊天详情", businessType = BusinessType.EXPORT)
    @PostMapping("/dialog/export/{id}")
    public void export(HttpServletResponse response, @PathVariable String id) {
        List<JkDialogRespDTO> dialogs = iJkRagService.exportExcel(id);
        ExcelUtil.exportExcel(dialogs,"聊天记录",JkDialogRespDTO.class,response);
    }

    @GetMapping("/role/list")
    public R<List<JkApplicationResult>> rolerApp() {
        List<JkApplicationResult> appList = iJkRagService.selectRoleApp();
        return R.ok(appList);
    }

    /**
     * 保存聊天记录
     *
     * @param dialogReqDTO
     * @return
     */
    @PostMapping("/dialog/save")
    public R<Void> saveDialog(@RequestBody JkDialogReqDTO dialogReqDTO) {
        LoginUser loginUser = null;
        if(StpUtil.isLogin()){
            loginUser = LoginHelper.getLoginUser();
        }

        if (loginUser != null) {
            dialogReqDTO.setUserId(String.valueOf(loginUser.getUserId()));
        }
        iJkRagService.saveDialog(dialogReqDTO);
        return R.ok();
    }

    /**
     * 聊天集合
     *
     * @return
     */
    @SaIgnore
    @GetMapping("/dialog/list/{appId}")
    public R<List<Object>> dialogList(@PathVariable String appId) {
        //LoginUser loginUser = LoginHelper.getLoginUser();
        String userId = null;
        if (StpUtil.isLogin()) {
            LoginUser loginUser = LoginHelper.getLoginUser();
            userId = String.valueOf(loginUser.getUserId());

        }
        List<Object> dialogs = iJkRagService.getDialogList(appId, userId);
        return R.ok(dialogs);
    }

    /**
     * 聊天详情
     *
     * @param dialogId
     * @return
     */
    @GetMapping("/dialog/detail/{dialogId}")
    public R<List<JkDialogRespDTO>> dialogDetail(@PathVariable String dialogId) {
        List<JkDialogRespDTO> detail = iJkRagService.getDialogDetail(dialogId);
        return R.ok(detail);
    }

    /**
     * 删除聊天记录
     *
     * @param id
     * @return
     */
    @DeleteMapping("/dialog/del/{id}")
    public R<Void> delDialog(@PathVariable String id) {
        iJkRagService.DelDialogDetail(id);
        return R.ok();
    }

    /**
     * 聊天标题重命名
     *
     * @param dialogReqDTO
     * @return
     */
    @PutMapping("/dialog/update")
    public R<Void> updateDialog(@RequestBody JkDialogReqDTO dialogReqDTO) {
        iJkRagService.updateDialog(dialogReqDTO);
        return R.ok();
    }

    /**
     * 预设问题
     *
     * @param appId
     * @return
     */
    @SaIgnore
    @GetMapping("/presets/{appId}")
    public R<List<String>> presets(@PathVariable String appId) {
        List<JkQuestionDTO> list = iJkRagService.selectQuestionByAppId(appId);
        List<String> strList = new ArrayList();
        for (JkQuestionDTO vo : list) {
            strList.add(vo.getQuestion());
        }
        return R.ok(strList);
    }

    /**
     * 预设问题
     *
     * @param appId
     * @return
     */
    @GetMapping("/free/presets/{appId}")
    public R<List<String>> freePresets(@PathVariable String appId) {
        return presets(appId);
    }


    /**
     *
     * 类型列表
     * @param dictType
     * @return
     */
    @GetMapping(value = "/{dictType}")
    public R<List<SysDictDataVo>> geDictInfo(@PathVariable String dictType) {
        SysDictDataBo dictData = new SysDictDataBo();
        dictData.setDictType(dictType);
        List<SysDictDataVo> dictDataList = dictDataService.selectDictDataList(dictData);
        return R.ok(dictDataList);
    }

    /**
     *
     * 类型列表
     * @param
     * @return
     */
    @GetMapping(value = "/projectTree")
    public R<List<TreeStruct>> getPorjectTree() {
        SysDictDataBo dictData = new SysDictDataBo();
        dictData.setDictType("project_type");
        List<SysProject> projectList = sysProjectService.selectSysProjectList(null);
        List<TreeStruct> projectTreeList = new ArrayList<>();
        TreeStruct projectType = new TreeStruct();
        List<TreeStruct> children = new ArrayList<>();
        for(SysProject project : projectList) {
            TreeStruct child = new TreeStruct();
            child.setValue(String.valueOf(project.getProjectId()));
            child.setLabel(project.getProjectName());
            children.add(child);
        }
        return R.ok(children);
    }

    /**
     * 应用类型列表
     * @return
     */
    @GetMapping("/appType")
    public R<List<Object>> appType() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser != null) {
            SysDictDataBo dictData = new SysDictDataBo();
            dictData.setDictType("app_type");
            List<SysDictDataVo> dictDataList = dictDataService.selectDictDataList(dictData);
            List<Object> list = iJkRagService.searchAppTypeGroupList(dictDataList, String.valueOf(loginUser.getUserId()));
            return R.ok(list);
        } else {
            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }
//        return null;
    }

    /**
     * 审核列表
     * @param params
     * @return
     */
    @PostMapping("/app/audit/list")
    public TableDataInfo documentAuditList(@RequestBody JkApplicationParams params,@RequestBody PageQuery pageQuery) {
        //startPage();
        Page<JkApplication> list = iJkRagService.applicationPageListByApprover(params,pageQuery);
        return TableDataInfo.build(list);
    }

    /**
     * 审核列表
     * @param params
     * @return
     */
    @PostMapping("/app/auditHistory/list")
    public TableDataInfo documentAuditHistoryList(@RequestBody JkApplicationParams params,@RequestBody PageQuery pageQuery) {
        //startPage();
        Page<JkApplication> list = iJkRagService.applicationHistoryPageListByApprover(params,pageQuery);
        return TableDataInfo.build(list);
    }

    /**
     * 开始审核
     * @return
     */
    @PutMapping(value = "/audit/{appId}/{userId}")
    public R<Integer> startAudit(@PathVariable String appId, @PathVariable String userId){
        return R.ok(iJkRagService.startAudit(appId, userId));
    }



    private JkApplication setFlagParams(String userId, String typeId, String projectId, int i) {
        if(i == 3){
            return returnParams(userId, typeId, projectId, "0");
        }else{
            Set<String> permissions = permissionService.getMenuPermission(Long.parseLong(userId));
            if (permissions.contains("deepseek:application:create") || permissions.contains("deepseek:application:update")) {
                return returnParams(userId, typeId, projectId, "1");
            }else{
                return returnParams(userId, typeId, projectId, "0");
            }
        }
    }

    private JkApplication returnParams(String userId, String typeId, String projectId, String flag) {
        return JkApplication.builder().approver(userId == null ? null : userId)
                .typeId(typeId == null ? null : Long.valueOf(typeId))
                .projectId(projectId == null ? null : projectId)
                .flag(flag).build();
    }

    @GetMapping("/test")
    public R<JkMediaReplacement> test() {
        JkMediaReplacement vo = iJkRagService.getJkMediaReplacement();
        return R.ok(vo);
    }


//    @GetMapping("/download/{fileName}")
//    public void downloadFile(@PathVariable String fileName) {
//        try {
////            InputStream stream = minioUtil.download(bucketName, fileName);
//            // 这里简化处理，实际应该设置正确的Content-Type和Content-Disposition
////            return ResponseEntity.ok()
////                    .header("Content-Type", "application/octet-stream")
////                    .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
////                    .body(stream);
//        } catch (Exception e) {
//            logger.error("文件下载失败: " + e.getMessage());
//        }
//    }

//    @DeleteMapping("/delete/{fileName}")
//    public void deleteFile(@PathVariable String fileName) {
//        try {
////            minioUtil.remove(bucketName, fileName);
//        } catch (Exception e) {
//            logger.error("文件删除失败: " + e.getMessage());
//        }
//    }

}
