package com.backendsys.modules.crt.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.backendsys.exception.CustException;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.crt.dao.CrtDramaProjectSettingsDao;
import com.backendsys.modules.crt.dao.CrtDramaProjectStoryboardDao;
import com.backendsys.modules.crt.dao.CrtGenerateImageDao;
import com.backendsys.modules.crt.dao.CrtModelDao;
import com.backendsys.modules.crt.entity.CrtDramaProjectSettings;
import com.backendsys.modules.crt.entity.CrtDramaProjectStoryboard;
import com.backendsys.modules.crt.entity.CrtGenerateImage;
import com.backendsys.modules.crt.entity.CrtModel;
import com.backendsys.modules.crt.enums.AspectRatioEnums;
import com.backendsys.modules.crt.enums.SamplerEnums;
import com.backendsys.modules.crt.service.CrtGenerateService;
import com.backendsys.modules.sdk.comfyui.entity.ComfyuiResponse;
import com.backendsys.modules.sdk.comfyui.entity.ComfyuiQueue;
import com.backendsys.modules.sdk.comfyui.entity.ComfyuiText2Image;
import com.backendsys.modules.sdk.comfyui.service.ComfyuiService;
import com.backendsys.modules.sdk.comfyui.service.ComfyuiSocketService;
import com.backendsys.modules.sdk.comfyui.service.ComfyuiTaskService;
import com.backendsys.modules.sdk.comfyui.service.ComfyuiText2ImageService;
import com.backendsys.modules.upload.enums.StyleEnums;
import com.backendsys.modules.upload.utils.UploadUtil;
import com.backendsys.utils.response.PageEntity;
import com.backendsys.utils.response.PageInfoResult;
import com.backendsys.utils.v2.PageUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

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

@Service
public class CrtGenerateServiceImpl implements CrtGenerateService {

    @Value("${comfyui.is-save}")
    private Boolean IS_SAVE;

    @Autowired
    private ComfyuiService comfyuiService;
    @Autowired
    private ComfyuiSocketService comfyuiSocketService;
    @Autowired
    private ComfyuiTaskService comfyuiTaskService;

    @Autowired
    private ComfyuiText2ImageService comfyuiText2ImageService;

    @Autowired
    private CrtModelDao crtModelDao;
    @Autowired
    private CrtDramaProjectSettingsDao crtDramaProjectSettingsDao;
    @Autowired
    private CrtDramaProjectStoryboardDao crtDramaProjectStoryboardDao;
    @Autowired
    private CrtGenerateImageDao crtGenerateImageDao;

    /**
     * [ComfyUI] 查询任务队列
     */
    @Override
    public Map<String, Object> getQueue(Integer port) {
        // [ComfyUI] 执行任务
        Mono<ComfyuiQueue> cfQueueMono = comfyuiService.getQueue(port);
        ComfyuiQueue response = cfQueueMono.block();
        System.out.println("结果: " + response);

        Map<String, Object> resp = new LinkedHashMap<>();
        resp.put("response", response);
        return resp;
    }

    /**
     * 短剧创作-生成图片
     */
    @Override
    public Map<String, Object> generateImage(CrtDramaProjectStoryboard crtDramaProjectStoryboard) {

        // 分镜ID
        Long drama_project_storyboard_id = crtDramaProjectStoryboard.getDrama_project_storyboard_id();

        CrtDramaProjectStoryboard storyboardDetail = crtDramaProjectStoryboardDao.selectById(drama_project_storyboard_id);
        if (storyboardDetail == null) throw new CustException("分镜不存在");

        Long drama_project_id = storyboardDetail.getDrama_project_id();
        LambdaQueryWrapper<CrtDramaProjectSettings> wrapperSettings = new LambdaQueryWrapper<>();
        wrapperSettings.eq(CrtDramaProjectSettings::getDrama_project_id, drama_project_id);
        List<CrtDramaProjectSettings> settingsDetail = crtDramaProjectSettingsDao.selectList(wrapperSettings);
        if (settingsDetail == null) throw new CustException("项目配置不存在");

        // 项目配置类型 (1:生图配置, 2:生视频配置)
        CrtDramaProjectSettings settings_image = settingsDetail.stream().filter(item -> item.getDrama_project_setting_type() == 1).findFirst().orElse(null);
        // CrtDramaProjectSettings settings_video = settingsDetail.stream().filter(item -> item.getDrama_project_setting_type() == 2).findFirst().orElse(null);


        // == 从生图参数初始化 ===========================================================================================
        String prompt_text = crtDramaProjectStoryboard.getText_to_image_prompt();                 // 文生图提示词
        Integer param_batch_size = storyboardDetail.getParam_batch_size();                        // 生成图片数量
        Float param_prompt_flux_guidance = storyboardDetail.getParam_prompt_flux_guidance();      // 提示词引导系数
        String param_sampler = SamplerEnums.getValueByKey(storyboardDetail.getParam_sampler());   // 采样器
        Integer param_step = storyboardDetail.getParam_step();                                    // 步数

        // 随机种子 (默认值：1，范围：(1:随机, 2:自定义))
        Integer param_seed_type = storyboardDetail.getParam_seed_type();
        String param_seed = (param_seed_type == 1) ?
                Convert.toStr(DateUtil.current()) :
                storyboardDetail.getParam_seed();

        // 画面比例 (从项目配置)(16:9 - 1280*720, 9:16 - 720*1280, 1:1 - 1024*1024)
        AspectRatioEnums aspect_ratio_option = AspectRatioEnums.of(settings_image.getAspect_ratio());
        Integer width = aspect_ratio_option.getWidth();     // 1280
        Integer height = aspect_ratio_option.getHeight();   // 720

        // 获取基础模型 (从项目配置)
        Long model_id = settings_image.getModel_id();
        CrtModel modelDetail = crtModelDao.selectById(model_id);
        String model_name = modelDetail.getModel_name();
        // =========================================================================================================


        // [DB] 更新分集详情记录 (更新种子值、提示词)
        CrtDramaProjectStoryboard entity = new CrtDramaProjectStoryboard();
        entity.setParam_seed(param_seed);
        entity.setText_to_image_prompt(prompt_text);
        LambdaQueryWrapper<CrtDramaProjectStoryboard> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrtDramaProjectStoryboard::getId, drama_project_storyboard_id);
        crtDramaProjectStoryboardDao.update(entity, wrapper);

        // 风格 Lora 待定
        // 风格 Lora （阙值）待定


        // ===========================================================================================================

        // -- [ComfyUI] 生图参数 ---------------------------------------------------
        ComfyuiText2Image comfyuiText2Image = new ComfyuiText2Image();
        comfyuiText2Image.setBatch_size(param_batch_size);
        comfyuiText2Image.setPrompt_flux_guidance(param_prompt_flux_guidance);
        comfyuiText2Image.setSampler(param_sampler);
        comfyuiText2Image.setStep(param_step);
        comfyuiText2Image.setWidth(width);
        comfyuiText2Image.setHeight(height);
        comfyuiText2Image.setModel_name(model_name);
        comfyuiText2Image.setPrompt_text(prompt_text);
        comfyuiText2Image.setSeed(param_seed);

        String client_id = Convert.toStr(UUID.randomUUID());

        // -- [ComfyUI] 发起生图任务 -----------------------------------------------
        Long task_id = comfyuiText2ImageService.generateText2Image(client_id, comfyuiText2Image);
        System.out.println("[创建生图任务] task_id = " + task_id);

        // -- [Rabbitmq] 推送到生成队列 --------------------------------------------
        Long user_id = SecurityUtil.getUserId();
        Map<String, Object> map = new HashMap<>();
        map.put("drama_project_storyboard_id", drama_project_storyboard_id);
        map.put("user_id", user_id);
        String custom_params = JSONUtil.toJsonStr(map);
        comfyuiTaskService.tryPushNext(user_id, custom_params);



//        // -- [ComfyUI] 创建 WebSocket 监听进度 --------------------------
//        Map<String, Object> params = new LinkedHashMap<>();
//        params.put("drama_project_storyboard_id", drama_project_storyboard_id);
//        // - is_save: 是否转存到 cos/tos
//        comfyuiSocketService.connectToSse(client_id, 8000, IS_SAVE, params).subscribe();

        // -- [ComfyUI] 执行/排队生图任务 --------------------------------------------

//        ComfyuiResponse response = comfyuiText2ImageService.generateText2Image(client_id, comfyuiText2Image);
//        System.out.println("结果: " + response);
//        // 结果: ComfyuiResponse(client_id=1a8a2d01-5500-437f-bb11-7a986130da48, prompt_id=c74501ed-6755-48f8-a440-aef3474b523c, number=47, node_errors={}, error=null)





        Map<String, Object> resp = new LinkedHashMap<>();
        resp.put("drama_project_storyboard_id", drama_project_storyboard_id);
        resp.put("client_id", client_id);
        resp.put("task_id", task_id);
//        resp.put("response", response);
        return resp;
    }

    // 短剧创作-获取分集生图记录
    @Override
    public PageEntity selectGenerateImage(CrtDramaProjectStoryboard crtDramaProjectStoryboard) {
        PageUtils.startPage();  // 分页

        Long drama_project_storyboard_id = crtDramaProjectStoryboard.getDrama_project_storyboard_id();

        LambdaQueryWrapper<CrtGenerateImage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrtGenerateImage::getDrama_project_storyboard_id, drama_project_storyboard_id);
        wrapper.orderByDesc(CrtGenerateImage::getCreate_time);
        List<CrtGenerateImage> list = crtGenerateImageDao.selectList(wrapper);

        // 1) 完成分页实体渲染
        PageEntity pageEntity = new PageInfoResult(list).toEntity();

        // 加入缩略图
        if (!list.isEmpty()) {
            // 2) 分页列表格式化
            list = list.stream().map(item -> {
                item.setUrl_thumb(UploadUtil.getImageThumbUrl(item.getUrl(), item.getTarget(), 100, null, StyleEnums.THUMB_BACKGROUND.getValue()));
                return item;
            }).collect(Collectors.toList());

            // 3) 分页实体重新赋值
            List<Object> objectList = list.stream().map(item -> (Object) item).collect(Collectors.toList());
            pageEntity.setList(objectList);
        }

        return pageEntity;
    }

}
