package com.pdaaphm.biz.service.impl;

import com.pdaaphm.biz.domain.BaseResponse;
import com.pdaaphm.biz.domain.File;
import com.pdaaphm.biz.domain.SubAlgorithm;
import com.pdaaphm.biz.dto.RequestDTO;
import com.pdaaphm.biz.mapper.FileMapper;
import com.pdaaphm.biz.mapper.SubAlgorithmMapper;
import com.pdaaphm.biz.service.RunAlgorithmService;
import com.pdaaphm.common.config.PadaphmConfig;
import com.pdaaphm.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.io.FilenameFilter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;


@Service
public class RunPythonImpl implements RunAlgorithmService {

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private SubAlgorithmMapper subAlgorithmMapper;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public BaseResponse runAlgorithm(Long id, String url, RequestDTO requestDto) {

        // create http
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(3000);
        httpRequestFactory.setConnectTimeout(3000);
        httpRequestFactory.setReadTimeout(3000);
        WebClient webClient = WebClient.create(url);
        // send post
        Mono<BaseResponse> result = webClient.post()  // 使用POST方法
                .uri("/request")  // 指定URI
                .contentType(MediaType.APPLICATION_JSON)  // 设置Content-Type为application/json
                .bodyValue(requestDto)  // 设置请求body
                .retrieve()  // 执行请求
                .bodyToMono(BaseResponse.class)
                .onErrorResume(e -> {
                    logger.error("http request error!!!",e);
                    if (e instanceof TimeoutException) {
                        // 对超时错误进行处理
                        return Mono.just(BaseResponse.error("Timeout error"));
                    } else {
                        // 对其他错误进行处理
                        return Mono.just(BaseResponse.error("Other error"));
                    }
                });  // 将响应体转换为String
        // get response
        BaseResponse res = result.block();

        // save result path to subAlgorithm
        List<String> resultList = requestDto.getResultList();
        List<Map> subAlgorithmOutputList = subAlgorithmMapper.selectSubAlgorithmOutputList(id);
        if (resultList == null) {
            return res.error("算法未配置输出");
        }
        for (int i = 0; i < resultList.size(); i++) {
            String resultPath = resultList.get(i);
            Map subAlgorithmOutput = subAlgorithmOutputList.get(i);
            int lastIndex = resultPath.lastIndexOf("/");
            String dirs = resultPath.substring(0, lastIndex);
            String prefixName = resultPath.substring(lastIndex + 1);
            Map<String,String> map = getFinalNameAndPath(dirs, prefixName);
            if (map != null) {
                String prefix = PadaphmConfig.getResultPath();
                String s = map.get("path");
                if (s.startsWith(prefix)) {
                    s = s.replace(prefix,"/resultPath");
                    map.put("path", s);
                }
                File resultFile = new File();
                resultFile.setName(map.get("name"));
                resultFile.setPath(map.get("path"));
                resultFile.setType(File.ouputFlag);
                resultFile.setCreateTime(DateUtils.getNowDate());
                fileMapper.insertFile(resultFile);
                SubAlgorithm subAlgorithm = new SubAlgorithm();
                subAlgorithm.setId((Long) subAlgorithmOutput.get("id"));
                subAlgorithm.setAlgorithmId((Long) subAlgorithmOutput.get("algorithm_id"));
                subAlgorithm.setFieldId((Long) subAlgorithmOutput.get("field_id"));
                subAlgorithm.setUploadId(resultFile.getId());
                subAlgorithm.setCreateTime(DateUtils.getNowDate());
                subAlgorithmMapper.updateSubAlgorithm(subAlgorithm);
            }
            else {
                logger.error("输出文件未生成！");
                // todo 对程序结果产生负面影响的分子，应反馈给前端
                // update algorithm
            }
        }
        return res;
    }

    // todo return type is Map<String,String>
    public Map getFinalNameAndPath(String dirs, String prefixName) {
        // 指定目录路径
        java.io.File directory = new java.io.File(dirs);

        // 使用FilenameFilter筛选与已知文件名开头的文件
        String[] matchingFiles = directory.list((dir, name) -> name.startsWith(prefixName));

        Map<String,String> map = new HashMap<>();

        if (matchingFiles != null && matchingFiles.length == 1) {
            System.out.println("找到匹配的文件：");
            map.put("name",matchingFiles[0]);
            map.put("path",dirs + '/' + matchingFiles[0]);
            return map;
        } else if (matchingFiles != null && matchingFiles.length > 1) {
            // todo 工程内禁止使用System.out.print 日志统一使用log
            logger.error("找到多个匹配的文件，这不应该发生。");
            return null;
        } else {
            // todo 工程内禁止使用System.out.print 日志统一使用log
            logger.error("没有找到匹配的文件。");
            return null;
        }
    }
}
