package com.yfd.platform.modules.basedata.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.config.AlgorithmServerConfig;
import com.yfd.platform.config.HttpServerConfig;
import com.yfd.platform.config.ParentConfig;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.constant.SystemCode;
import com.yfd.platform.modules.basedata.domain.AlgorithmManufacturerVersion;
import com.yfd.platform.modules.basedata.domain.AlgorithmModel;
import com.yfd.platform.modules.basedata.service.IAlgorithmManufacturerVersionService;
import com.yfd.platform.modules.basedata.service.IAlgorithmModelService;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.service.IUserService;
import com.yfd.platform.utils.HttpRESTfulUtils;
import com.yfd.platform.utils.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.presets.opencv_core;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 算法模型表 前端控制器
 * </p>
 *
 *
 * @since 2023-08-25
 */
@RestController
@RequestMapping("/basedata/algorithmmodel")
@Api(value = "AlgorithmModelController", tags = "模型算法")
@Slf4j
public class AlgorithmModelController {

    @Resource
    private IAlgorithmModelService algorithmModelService;
    @Resource
    private HttpRESTfulUtils httpRESTfulUtils;
    @Resource
    private HttpServerConfig httpServerConfig;
    @Resource
    private AlgorithmServerConfig algorithmServerConfig;

    @Resource
    private IAlgorithmManufacturerVersionService manufacturerVersionService;

    @ApiOperation("获取算法模型列表")
    @GetMapping("/getAlgorithmModelList")
    public ResponseResult getAlgorithmModelList(Page<Map<String, Object>> page, String stationId, String modelCode,
                                                String modelName, String isnew, String runstate,String type) {
        LambdaQueryWrapper<AlgorithmModel> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(stationId)) {
            queryWrapper.eq(AlgorithmModel::getStationId, stationId);
        }
        if (StrUtil.isNotEmpty(modelCode)) {
            queryWrapper.eq(AlgorithmModel::getModelCode, modelCode);
        }
        if (StrUtil.isNotEmpty(isnew)) {
            queryWrapper.eq(AlgorithmModel::getIsnew, isnew);
        }
        if (StrUtil.isNotEmpty(runstate)) {
            queryWrapper.eq(AlgorithmModel::getRunstate, runstate);
        }
        if (StrUtil.isNotEmpty(type)) {
            queryWrapper.eq(AlgorithmModel::getModelType, type);
        }
        if (StrUtil.isNotEmpty(modelName)) {
            queryWrapper.like(AlgorithmModel::getModelName, modelName);
        }
        queryWrapper.eq(AlgorithmModel::getIsnew,"1").orderByAsc(AlgorithmModel::getStationName, AlgorithmModel::getModelType,
                AlgorithmModel::getModelCode, AlgorithmModel::getVersion);
        Page<Map<String, Object>> mapPage = algorithmModelService.pageMaps(page, queryWrapper);
        return ResponseResult.successData(mapPage);
    }

    @ApiOperation("根据主键获取单个算法模型信息")
    @GetMapping("/getAlgorithmModel")
    public ResponseResult getAlgorithmModel(String id) {
        AlgorithmModel algorithmModel = algorithmModelService.getById(id);
        return ResponseResult.successData(algorithmModel);
    }

    @ApiOperation("获取算法厂商历史版本列表")
    @GetMapping("/getManufacturerPage")
    public ResponseResult getManufacturerPage(Page<Map<String, Object>> page,String manufacturer) {
        LambdaQueryWrapper<AlgorithmManufacturerVersion> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(manufacturer)) {
            queryWrapper.eq(AlgorithmManufacturerVersion::getAlgorithmManufacturer, manufacturer);
        }
        Page<Map<String, Object>> mapPage = manufacturerVersionService.pageMaps(page, queryWrapper);
        return ResponseResult.successData(mapPage);
    }


    @Log(module = "算法模型", value = "新增或修改算法模型", type = "1")
    @PostMapping("/addOrUpdateAlgorithmModel")
    @ApiOperation("新增或修改算法模型")
    public ResponseResult addOrUpdateAlgorithmModel(@RequestBody AlgorithmModel algorithmModel) {
        if (StrUtil.isEmpty(algorithmModel.getId())) {
            //新增算法
            algorithmModel.setId(IdUtil.fastSimpleUUID());
            algorithmModel.setRecordtime(LocalDateTime.now());
            algorithmModel.setRunstate("2");
        }
        algorithmModel.setLastmodifier(SecurityUtils.getCurrentUsername());
        algorithmModel.setLastmodifydate(LocalDateTime.now());
        algorithmModelService.saveOrUpdate(algorithmModel);
        return ResponseResult.success();
    }


    @Log(module = "算法模型", value = "从算法平台下载模型", type = "1")
    @PostMapping("/downloadAlgorithmModel")
    @ApiOperation("从算法平台下载模型")
    public ResponseResult downloadAlgorithmModel(String ModelId) {
        //todo 从算法管理平台下载模型

        return ResponseResult.success();
    }

    @Log(module = "算法模型", value = "将当前版本模型更新到智能分析主机", type = "1")
    @PostMapping("/pushAlgorithmModelToAnalysisHost")
    @ApiOperation("将当前版本模型更新到智能分析主机")
    public ResponseResult pushAlgorithmModelToAnalysisHost(String ModelId) {
        if (StrUtil.isBlank(ModelId)) {
            return ResponseResult.error("参数为空");
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOnce("requestHostIp", httpServerConfig.getPatrolIp());
        jsonObject.putOnce("requestHostPort", httpServerConfig.getPatrolPort());
        jsonObject.putOnce("requestId", ModelId);
        AlgorithmModel algorithmModel = algorithmModelService.getById(ModelId);
        String modelFile = algorithmModel.getModelFile();
        String ftpUrl = "ftp://" + algorithmServerConfig.getServerIp() + ":2121/" + modelFile;
        jsonObject.putOnce("algorithmPath", ftpUrl);
        jsonObject.putOnce("requestHostAppname", httpServerConfig.getPatrolAppname());
        log.info(jsonObject.toString());
        httpRESTfulUtils.sendHttpPost("json", httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort13(),
                "", "algorithmUpdate", jsonObject, null);
        //todo 将当前版本模型更新到智能分析主机
        return ResponseResult.success();
    }

    //    @Log(module = "算法版本获取接口", value = "巡视主机向算法管理平台认证获取token")
    //    @PostMapping("/getToken")
    //    @ApiOperation("巡视主机向算法管理平台认证获取token")
    //    public String  getToken() {
    //        SysUser userInfo = userService.getUserInfo();
    //        JSONObject jsonObject = new JSONObject();
    //        jsonObject.putOnce("Username", userInfo.getUsername());
    //        jsonObject.putOnce("Password", userInfo.getPassword());
    //        com.alibaba.fastjson.JSONObject responseData = httpRESTfulUtils.sendHttpPost("json",
    //                httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort11(), "",
    //                "recogApi/token", jsonObject, null);
    //        return ResponseResult.successData(responseData);
    //    }

    /**********************************
     * 用途说明: 获取算法管理平台调用Token
     * 参数说明
     * 返回值说明: java.lang.String
     ***********************************/
    private String getToken() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOnce("Username", algorithmServerConfig.getUsername());
        jsonObject.putOnce("Password", algorithmServerConfig.getPassword());
        //        Map<String, Object> param = new HashMap<>();
        //        param.put("param", jsonObject);
        com.alibaba.fastjson.JSONObject responseData = httpRESTfulUtils.sendHttpPost("json",
                algorithmServerConfig.getServerIp(), algorithmServerConfig.getHttpPort(), "", "recogApi/token",
                jsonObject, null);
        if (!SystemCode.SUCCESS_STATUS_CODE.getCode().equals(responseData.getString("code"))) {
            return null;
        }
        return responseData.getString("Token");
    }

//    @Log(module = "算法版本获取接口", value = "获取当前该区域某站点的运行算法参数", type = "1")
//    @PostMapping("/getRecogParams")
//    @ApiOperation("获取当前该区域某站点的运行算法参数")
//    public ResponseResult getRecogParams(String sectionId, String stationId) {
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.putOnce("sectionId", sectionId);
//        jsonObject.putOnce("stationId", stationId);
//        //        Map<String, Object> param = new HashMap<>();
//        //        param.put("param", jsonObject);
//        String token = getToken();
//        com.alibaba.fastjson.JSONObject responseData = httpRESTfulUtils.sendHeaderHttpPost("json",
//                algorithmServerConfig.getServerIp(), algorithmServerConfig.getHttpPort(), "", token,
//                "runRecogApi/recogParams", jsonObject, null);
//        String code = responseData.getString("code");
//        if (!"200".equals(code)) {
//            String message = responseData.getString("message");
//            return ResponseResult.error(message);
//        }
//        JSONArray data = responseData.getJSONArray("data");
//        // 获取版本信息存放入数据库
//        for (int i = 0; i < data.size(); i++) {
//            AlgorithmModel algorithmModel = data.getObject(i, AlgorithmModel.class);
//            String algorithmmanufacturer = algorithmModel.getAlgorithmmanufacturer();
//            String version = algorithmModel.getVersion();
//            LambdaQueryWrapper<AlgorithmModel> queryWrapper = new LambdaQueryWrapper<>();
//            queryWrapper.eq(AlgorithmModel::getAlgorithmmanufacturer, algorithmmanufacturer).eq(AlgorithmModel::getVersion, version);
//            AlgorithmModel one = algorithmModelService.getOne(queryWrapper);
//            if (one != null) {
//                // 已经存在该版本数据 修改
//                algorithmModel.setId(one.getId());
//                algorithmModelService.updateById(algorithmModel);
//            } else {
//                LambdaUpdateWrapper<AlgorithmModel> updateWrapper = new LambdaUpdateWrapper<>();
//                updateWrapper.eq(AlgorithmModel::getIsnew, "1").set(AlgorithmModel::getIsnew, "0");
//                algorithmModelService.update(updateWrapper);
//                // 不存在该版本数据 新增
//                algorithmModel.setIsnew("1");
//                algorithmModel.setModelFile(version + ".zip");
//                algorithmModel.setModelCode("Model01");
//                algorithmModel.setModelName("Model01");
//                algorithmModel.setLastmodifier("算法更新");
//                algorithmModel.setRecordtime(LocalDateTime.now());
//                algorithmModel.setLastmodifydate(LocalDateTime.now());
//                algorithmModelService.save(algorithmModel);
//            }
//        }
//        return ResponseResult.success();
//    }
//
//    @Log(module = "算法版本获取接口", value = "获取算法厂商的算法版本信息", type = "1")
//    @PostMapping("/getHistoryVersion")
//    @ApiOperation("获取算法厂商的算法版本信息")
//    public ResponseResult getHistoryVersion(String algorithmManufacturer, String token) {
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.putOnce("algorithmManufacturer", algorithmManufacturer);
//        com.alibaba.fastjson.JSONObject responseData = httpRESTfulUtils.sendHeaderHttpPost("json",
//                httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort11(), "", token,
//                "recogApi/historyVersion", jsonObject, null);
//        return ResponseResult.successData(responseData);
//    }
//
//    @Log(module = "算法版本获取接口", value = "实现某区域某站端算法版本的更新或回退", type = "1")
//    @PostMapping("/updateAlgorithmVersion")
//    @ApiOperation("实现某区域某站端算法版本的更新或回退")
//    public ResponseResult updateAlgorithmVersion(String sectionId, String stationId, String version, String token) {
//        JSONObject jsonObject = new JSONObject();
//        jsonObject.putOnce("sectionId", sectionId);
//        jsonObject.putOnce("stationId", stationId);
//        jsonObject.putOnce("version", version);
//        com.alibaba.fastjson.JSONObject responseData = httpRESTfulUtils.sendHeaderHttpPost("json",
//                httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort11(), "", token,
//                "recogApi/updateAlgorithmVersion", jsonObject, null);
//        String code = responseData.getString("code");
//        if (!"200".equals(code)) {
//            String message = responseData.getString("message");
//            return ResponseResult.error(message);
//        }
//        String progress = "0%";
//        while (!"100%".equals(progress)) {
//            JSONObject jsonObject1 = new JSONObject();
//            jsonObject1.putOnce("stationId", stationId);
//            jsonObject1.putOnce("version", version);
//            jsonObject1.putOnce("progress", progress);
//            com.alibaba.fastjson.JSONObject responseData1 = httpRESTfulUtils.sendHeaderHttpPost("json",
//                    httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort11(), "", token,
//                    "recogApi/updateProgress", jsonObject1, null);
//            String code1 = responseData1.getString("code");
//            if (!"200".equals(code1)) {
//                String message = responseData1.getString("message");
//                return ResponseResult.error(message);
//            }
//
//            progress = responseData1.getString("progress");
//        }
//        return ResponseResult.success();
//    }


    @Log(module = "算法版本获取接口", value = "获取当前该区域某站点的运行算法参数", type = "1")
    @GetMapping("/getRecogParams")
    @ApiOperation("获取当前该区域某站点的运行算法参数")
    @PreAuthorize("@el.check('select:model')")
    public ResponseResult getRecogParams(String sectionId, String stationId, String type) {
        algorithmModelService.getRecogParams(sectionId, stationId, type);
        return ResponseResult.success();
    }

    @Log(module = "算法版本获取接口", value = "获取算法厂商的算法版本信息", type = "1")
    @GetMapping("/getHistoryVersion")
    @ApiOperation("获取算法厂商的算法版本信息")
    @PreAuthorize("@el.check('select:model')")
    public ResponseResult getHistoryVersion(String algorithmManufacturer, String sectionId, String stationId,
                                            String type) {
        algorithmModelService.getHistoryVersion(sectionId, stationId, type,algorithmManufacturer);
        return ResponseResult.success();
    }

    @Log(module = "算法版本获取接口", value = "实现某区域某站端算法版本的更新或回退", type = "1")
    @GetMapping("/updateAlgorithmVersion")
    @ApiOperation("实现某区域某站端算法版本的更新或回退")
    public ResponseResult updateAlgorithmVersion(String sectionId, String stationId, String type, String version) {
        algorithmModelService.updateAlgorithmVersion(sectionId, stationId, type,version);
        return ResponseResult.success();
    }

        /*@Log(module = "算法版本获取接口", value = "巡视主机向算法管理平台获取更新进度和结果")
        @PostMapping("/updateProgress")
        @ApiOperation("巡视主机向算法管理平台获取更新进度和结果")
        public ResponseResult updateProgress(String stationId, String version, String progress, String token) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.putOnce("stationId", stationId);
            jsonObject.putOnce("version", version);
            jsonObject.putOnce("progress", progress);
            com.alibaba.fastjson.JSONObject responseData = httpRESTfulUtils.sendHeaderHttpPost("json",
                    httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort11(), "", token,
                    "recogApi/updateProgress", jsonObject, null);
            return ResponseResult.successData(responseData);
        }*/

    @Log(module = "模型算法", value = "上传文件", type = "1")
    @PostMapping("/uploadModelFile")
    @ApiOperation("上传文件")
    @ResponseBody
    public ResponseResult uploadModelFile(MultipartFile file, String modelId) throws FileNotFoundException {
        String filename = file.getOriginalFilename();
        String suffix = StrUtil.subAfter(filename, ".", true);
        if (!"pdf".equals(suffix)) {
            return ResponseResult.error("非法文件类型");
        }
        String contentType = file.getContentType();
        if ("application/pdf".equals(contentType)) {
            return ResponseResult.error("非法文件内容");
        }
        algorithmModelService.uploadModelFile(file, modelId);
        return ResponseResult.success();
    }

    @GetMapping("/viewModelFile")
    @ApiOperation("预览模型文件")
    public void viewModelFile(String fileName, HttpServletResponse response) throws IOException {
        if (StrUtil.isBlank(fileName)) {
            throw new RuntimeException("文件名是空的");
        }
        if (fileName.contains("\\") || fileName.contains("/")) {
            throw new RuntimeException("非法文件路径");
        }
        String suffix = StrUtil.subAfter(fileName, ".", true).toLowerCase();
        if (!"pdf".equals(suffix)) {
            throw new RuntimeException("非法文件类型");
        }
        algorithmModelService.viewModelFile(fileName, response);
    }

    @PostMapping("/deleteModelFile")
    @ApiOperation("删除文件")
    public ResponseResult deleteModelFile(String id, String fileName) {
        if (StrUtil.isBlank(fileName)) {
            throw new RuntimeException("文件名是空的");
        }
        if (fileName.contains("\\") || fileName.contains("/")) {
            throw new RuntimeException("非法文件路径");
        }
        String suffix = StrUtil.subAfter(fileName, ".", true).toLowerCase();
        if (!"pdf".equals(suffix)) {
            throw new RuntimeException("非法文件类型");
        }
        int count = algorithmModelService.count(new LambdaQueryWrapper<AlgorithmModel>().eq(AlgorithmModel::getId, id).eq(AlgorithmModel::getModelFile, fileName));
        if (count < 0) {
            return ResponseResult.error("删除失败");
        }
        boolean ok = algorithmModelService.deleteModelFile(id, fileName);
        if (ok) {
            return ResponseResult.success();
        } else {
            return ResponseResult.error("删除失败");
        }
    }

    @PostMapping("/uploadModel")
    @ApiOperation("上传文件")
    @ResponseBody
    public ResponseResult uploadModel(String id,String type,String filePath)  {
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOnce("requestHostIp", httpServerConfig.getPatrolIp());
        jsonObject.putOnce("requestHostPort", httpServerConfig.getPatrolPort());
        jsonObject.putOnce("requestId", id);
        jsonObject.putOnce("type", type);
        String ftpUrl =
                "ftp://" + algorithmServerConfig.getFtpUsername() + ":" + algorithmServerConfig.getFtpPassword() + "@" + algorithmServerConfig.getServerIp() + ":" + algorithmServerConfig.getFtpPort() + "/" + filePath;
        jsonObject.putOnce("algorithmPath", ftpUrl);
        log.info(jsonObject.toString());
        com.alibaba.fastjson.JSONObject jsonObject1 = httpRESTfulUtils.sendHttpPost("json",
                httpServerConfig.getAnalyseIp(), httpServerConfig.getAnalysePort13(), "",
                "algorithmUpdate", jsonObject, null);
        return ResponseResult.success();
    }

}
