package com.backendsys.service.Ali;

import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.backendsys.aspect.HttpRequestAspect;
import com.backendsys.entity.Ali.AliDashscopeBackgroundDTO;
import com.backendsys.entity.Ali.AliDashscopeBackgroundInputDTO;
import com.backendsys.entity.Ali.AliDashscopeTaskDTO;
import com.backendsys.entity.Ali.AliDashscopeTaskResultDTO;
import com.backendsys.mapper.Ali.AliDashscopeTaskMapper;
import com.backendsys.utils.ResourceUtil;
//import org.apache.http.protocol.HttpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.List;
import java.util.Map;

@Service
public class AliDashscopeServiceImpl implements AliDashscopeService {

    @Value("${file.upload.directory}") // 配置保存文件的目录
    private String uploadDirectory;

    @Value("${aliyun.dashscope.url}")
    private String baseUrl;

    @Value("${aliyun.dashscope.api-key}")
    private String API_KEY;

    @Autowired
    private AliDashscopeTaskMapper aliDashscopeTaskMapper;

    @Autowired
    private HttpRequestAspect httpRequestAspect;


    /**
     * 通义万相 - 查询任务生成结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> getTaskById(String task_id) {

        // Http 远程调用
        Map<String, Object> resp = WebClient.create()
            .method(HttpMethod.GET)
            .uri(baseUrl + "/api/v1/tasks/" + task_id)
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .header(HttpHeaders.AUTHORIZATION, "Bearer " + API_KEY)
            .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
            .block();

        // .block() 是同步写法
        /*
            以下是异步写法：
            resp.subscribe(resp -> {
                // 处理响应体的逻辑
            }, error -> {
                // 处理错误的逻辑
            });
         */

        // [DB] 更新任务记录
//        Map<String, Object> output = (Map<String, Object>) resp.get("output");
//        String output_task_id = (String) output.get("task_id");
        Map<String, Object> output = Convert.toMap(String.class, Object.class, resp.get("output"));
        String output_task_id = Convert.toStr(output.get("task_id"));

        AliDashscopeTaskDTO aliDashscopeTaskDTO = new AliDashscopeTaskDTO();
        aliDashscopeTaskDTO.setTask_id(output_task_id);
        aliDashscopeTaskDTO.setTask_status((String) output.get("task_status"));

        List<Map<String, Object>> results = (List<Map<String, Object>>) output.get("results");
        if (results != null && !results.isEmpty()) {

            String submit_time = (String) output.get("submit_time");
            String scheduled_time = (String) output.get("scheduled_time");
            String end_time = (String) output.get("end_time");
            aliDashscopeTaskDTO.setSubmit_time(submit_time);
            aliDashscopeTaskDTO.setScheduled_time(scheduled_time);
            aliDashscopeTaskDTO.setEnd_time(end_time);

            Map<String, Object> task_metrics = (Map<String, Object>) output.get("task_metrics");
            if (task_metrics != null) {
                aliDashscopeTaskDTO.setTask_metrics_total((Integer) task_metrics.get("TOTAL"));
                aliDashscopeTaskDTO.setTask_metrics_succeeded((Integer) task_metrics.get("SUCCEEDED"));
                aliDashscopeTaskDTO.setTask_metrics_failed((Integer) task_metrics.get("FAILED"));
            }


            // 判断是否存在结果，如果不存在，则新增
            AliDashscopeTaskResultDTO aliDashscopeTaskResultDTO = new AliDashscopeTaskResultDTO();
            aliDashscopeTaskResultDTO.setTask_id(output_task_id);
            List<Map<String, Object>> response = aliDashscopeTaskMapper.queryDashscopeTaskResultList(aliDashscopeTaskResultDTO);

            if (response == null || response.isEmpty()) {
                // 遍历结果列表
                // - 手动添加 task_id
                // - 手动添加 url_local 本地图片路径
                for (Map<String, Object> map : results) {

                    // (待修改) 1.改成本地；2.改成COS储存
                    String url = (String) map.get("url");

                    // 判断远程图片是否有效，有则保存到本地 (或 COS)
//                    System.out.println("---------------------------------------------------------");
//                    System.out.println("checkImageValid: " + ResourceUtil.checkImageValid(url));
//                    System.out.println(url);
//                    System.out.println("---------------------------------------------------------");

                    if (ResourceUtil.checkImageValid(url)) {
                        String url_local = ResourceUtil.downloadImage(url, uploadDirectory);
                        map.put("url_local", url_local);

                        System.out.println("url_local: " + url_local);
                        System.out.println("---------------------------------------------------------");
                    }
                    map.put("task_id", output_task_id);

                }

//                System.out.println("results:");
//                System.out.println(results);
//                System.out.println("---------------------------------------------------------");

                output.put("results", results);
                resp.put("output", output);

                // 新增任务记录所关联的 结果
                aliDashscopeTaskMapper.insertDashscopeTaskResult(results);
            }
        }

        // 更新任务记录
        aliDashscopeTaskMapper.updateDashscopeTask(aliDashscopeTaskDTO);

        // 怪异，有时拿的到 url_local，有时拿不到？？？
//        System.out.println("output:");
//        System.out.println(output);
//        System.out.println("-------------------------------");
//        System.out.println("resp2:");
//        System.out.println(resp);
//        System.out.println("==================================");

        return resp;
    }

    /**
     * 通义万相 - 图像背景生成API
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> createBackgroundGenerationTask(AliDashscopeBackgroundDTO aliDashscopeBackgroundDTO) {

        aliDashscopeBackgroundDTO.setModel("wanx-background-generation-v2");
        String data = JSONUtil.toJsonStr(aliDashscopeBackgroundDTO);

        // Http 远程调用
        Map<String, Object> resp = WebClient.create()
            .method(HttpMethod.POST)
            .uri(baseUrl + "/api/v1/services/aigc/background-generation/generation/")
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .header(HttpHeaders.AUTHORIZATION, "Bearer " + API_KEY)
            .header("X-DashScope-Async", "enable")
            .bodyValue(data)
            .retrieve().bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
            .block();

        // .block() 是同步写法
        /*
            以下是异步写法：
            resp.subscribe(resp -> {
                // 处理响应体的逻辑
            }, error -> {
                // 处理错误的逻辑
            });
         */

        // [DB] 新增任务记录
        Map<String, Object> output = (Map<String, Object>) resp.get("output");
        AliDashscopeTaskDTO aliDashscopeTaskDTO = new AliDashscopeTaskDTO();
        aliDashscopeTaskDTO.setRequest_id((String) resp.get("request_id"));
        aliDashscopeTaskDTO.setTask_id((String) output.get("task_id"));
        aliDashscopeTaskDTO.setTask_status((String) output.get("task_status"));

        // 插入原主图
        AliDashscopeBackgroundInputDTO input = aliDashscopeBackgroundDTO.getInput();
        String base_image_url = input.getBase_image_url();
        aliDashscopeTaskDTO.setThumb(base_image_url);

        // 要再插入生成好的图？


        // [查询] 自身 UserId (并加入)
        Long user_id = httpRequestAspect.getUserId();
        aliDashscopeTaskDTO.setUser_id(user_id);

        aliDashscopeTaskMapper.insertDashscopeTask(aliDashscopeTaskDTO);

        return resp;

    }

}
