package com.backendsys.modules.ai.volcengine.service.impl;

import com.backendsys.exception.CustException;
import com.backendsys.modules.ai.volcengine.dao.VolcengineVideoTaskDao;
import com.backendsys.modules.ai.volcengine.entity.VolcengineVideoTask;
import com.backendsys.modules.ai.volcengine.entity.VolcengineVideoTaskDTO;
import com.backendsys.modules.ai.volcengine.entity.VolcengineVideoTaskDetail;
import com.backendsys.modules.ai.volcengine.entity.VolcengineVideoTaskNotify;
import com.backendsys.modules.ai.volcengine.service.VolcengineVideoTaskDetailService;
import com.backendsys.modules.ai.volcengine.service.VolcengineVideoTaskService;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.upload.entity.SysFileResult;
import com.backendsys.modules.upload.service.SysFileService;
import com.backendsys.utils.response.PageEntity;
import com.backendsys.utils.response.PageInfoResult;
import com.backendsys.utils.v2.PageUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.volcengine.ark.runtime.model.content.generation.CreateContentGenerationTaskRequest;
import com.volcengine.ark.runtime.model.content.generation.CreateContentGenerationTaskResult;
import com.volcengine.ark.runtime.model.content.generation.GetContentGenerationTaskRequest;
import com.volcengine.ark.runtime.model.content.generation.GetContentGenerationTaskResponse;
import com.volcengine.ark.runtime.service.ArkService;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class VolcengineVideoTaskServiceImpl extends ServiceImpl<VolcengineVideoTaskDao, VolcengineVideoTask> implements VolcengineVideoTaskService {

    @Autowired
    private VolcengineVideoTaskDetailService volcengineVideoTaskDetailService;

    @Autowired
    private SysFileService sysFileService;

    @Value("${volcengine.api-key}")
    private String apiKey;

    @Value("${domain}")
    private String domain;

    private final ConnectionPool connectionPool = new ConnectionPool(20, 5, TimeUnit.MINUTES);
    private final Dispatcher dispatcher = new Dispatcher();
    private ArkService service;

    @PostConstruct
    public void init() {
        this.service = ArkService.builder()
                .dispatcher(dispatcher)
                .connectionPool(connectionPool)
                .apiKey(apiKey)
                .build();
    }

    @Transactional
    @Override
    public VolcengineVideoTask generateVideo(VolcengineVideoTask volcengineVideoTask) {
        // 生成任务主表记录
        this.baseMapper.insert(volcengineVideoTask);

        List<CreateContentGenerationTaskRequest.Content> contents = new ArrayList<>();

        // 图生视频功能 构建请求参数
        // 文本提示词与参数组合
        if (StringUtils.isBlank(volcengineVideoTask.getText())) {
            volcengineVideoTask.setText("");
        }
        StringBuilder text = new StringBuilder(volcengineVideoTask.getText());
        if(StringUtils.isNotBlank(volcengineVideoTask.getResolution())) {
            text.append(" --rs ").append(volcengineVideoTask.getResolution());
        }
        if(volcengineVideoTask.getDuration() != null) {
            text.append(" --dur ").append(volcengineVideoTask.getDuration());
        }
        if(volcengineVideoTask.getCamerafixed() != null) {
            if (volcengineVideoTask.getCamerafixed() == 1) {
                text.append(" --cf true");
            } else {
                text.append(" --cf false");
            }
        }

        contents.add(CreateContentGenerationTaskRequest.Content.builder()
                .type("text")
                .text(text.toString())
                .build());

        // 首帧图片 (若仅需使用文本生成视频功能，可将此部分内容进行注释处理。)
        contents.add(CreateContentGenerationTaskRequest.Content.builder()
                .type("image_url")
                .imageUrl(CreateContentGenerationTaskRequest.ImageUrl.builder()
                        .url(volcengineVideoTask.getImg_url())
                        .build())
                .build());
        String notifyUrl = domain+ "/api/ai/volcengine/video/notify";
        // 创建视频生成任务
        CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
                .model(volcengineVideoTask.getModel())
                .content(contents)
                // 回调地址
                .callbackUrl(notifyUrl)
                .build();

        //根据数量生成任务，记录明细
        List<VolcengineVideoTaskDetail> detailList = new ArrayList<>();
        int num = 0;
        while (volcengineVideoTask.getQuantity() > num) {

            VolcengineVideoTaskDetail volcengineVideoTaskDetail = new VolcengineVideoTaskDetail();
            volcengineVideoTaskDetail.setTask_id(volcengineVideoTask.getId());
            volcengineVideoTaskDetail.setUser_id(volcengineVideoTask.getUser_id());
            volcengineVideoTaskDetail.setCover_img_url(volcengineVideoTask.getImg_url());
            volcengineVideoTaskDetail.setStatus("queued");
            // 创建图生视频任务
            CreateContentGenerationTaskResult taskResult = service.createContentGenerationTask(createRequest);

            volcengineVideoTaskDetail.setVolcengine_task_id(taskResult.getId());
            detailList.add(volcengineVideoTaskDetail);
            num++;
        }
        if(!detailList.isEmpty()){
            volcengineVideoTaskDetailService.saveBatch(detailList);
            volcengineVideoTask.setDetail_list(detailList);
        }

        return volcengineVideoTask;
    }

    @Override
    public VolcengineVideoTaskDetail selectTaskStatus(String volcengineTaskId) {

        VolcengineVideoTaskDetail volcengineVideoTaskDetail = volcengineVideoTaskDetailService.getOne(Wrappers.<VolcengineVideoTaskDetail>lambdaQuery()
                .eq(VolcengineVideoTaskDetail::getVolcengine_task_id, volcengineTaskId));
        if(volcengineVideoTaskDetail == null) {
            throw new CustException("找不到该图生视频信息，请检查参数是否有误");
        }
        // 成功或失败的直接返回
        if("succeeded".equals(volcengineVideoTaskDetail.getStatus()) || "failed".equals(volcengineVideoTaskDetail.getStatus())) {
            return volcengineVideoTaskDetail;
        }

        GetContentGenerationTaskRequest getRequest = GetContentGenerationTaskRequest.builder()
                .taskId(volcengineTaskId)
                .build();

        GetContentGenerationTaskResponse response = service.getContentGenerationTask(getRequest);
        // 更新任务明细
        volcengineVideoTaskDetail.setStatus(response.getStatus());
        if(response.getSeed() != null) {
            volcengineVideoTaskDetail.setSeed(response.getSeed().intValue());
        }
        if("succeeded".equals(response.getStatus())) {
            // 成功，保存视频url
            String videoOriginUrl = response.getContent().getVideoUrl();
            volcengineVideoTaskDetail.setVideo_origin_url(videoOriginUrl);

            // URL转存文件
            SysFileResult sysFileResult = sysFileService.urlToUploadFile(videoOriginUrl, SecurityUtil.getUserId());
            String objectKey = sysFileResult.getKey();
            String videoUrl = sysFileResult.getDomain() + "/" + sysFileResult.getKey();
            volcengineVideoTaskDetail.setVideo_url(videoUrl);
            volcengineVideoTaskDetail.setObject_key(objectKey);
        } else {
            if(response.getError() !=null) {
                volcengineVideoTaskDetail.setError_msg(response.getError().toString());
            }
        }

        volcengineVideoTaskDetailService.updateById(volcengineVideoTaskDetail);

        return volcengineVideoTaskDetail;

    }

    @Override
    public PageEntity selectTaskList(VolcengineVideoTaskDTO dto) {
        PageUtils.startPage();
        List<VolcengineVideoTask> list = new ArrayList<>();
        // 时间范围
        if(dto.getDate_range() != null) {
            String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            switch (dto.getDate_range()) {
                case 0:
                    // 今天
                    dto.setCreate_begin_date(today);
                    dto.setCreate_end_date(today);
                    break;
                case 1:
                    // 昨天
                    String yesterday = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                    dto.setCreate_begin_date(yesterday);
                    dto.setCreate_end_date(yesterday);
                    break;
                case 2:
                    // 近3天
                    dto.setCreate_begin_date(LocalDate.now().minusDays(2).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    dto.setCreate_end_date(today);
                    break;
                case 3:
                    // 近5天
                    dto.setCreate_begin_date(LocalDate.now().minusDays(4).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    dto.setCreate_end_date(today);
                    break;
                case 4:
                    // 近7天
                    dto.setCreate_begin_date(LocalDate.now().minusDays(6).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    dto.setCreate_end_date(today);
                    break;
                case 5:
                    // 近14天
                    dto.setCreate_begin_date(LocalDate.now().minusDays(13).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    dto.setCreate_end_date(today);
                    break;
            }
        }
        if(dto.getOnly_collections() != null && dto.getOnly_collections() == 1){
            // 只看收藏
            list = baseMapper.selectTaskCollectList(dto);
        } else {
            list = baseMapper.selectTaskList(dto);
        }
        return new PageInfoResult(list).toEntity();
    }

    @Override
    public VolcengineVideoTaskDetail regenerate(VolcengineVideoTaskDetail volcengineVideoTaskDetail) {

        VolcengineVideoTaskDetail dataBean = volcengineVideoTaskDetailService.getById(volcengineVideoTaskDetail.getId());
        if(dataBean == null) {
            throw new CustException("任务不存在");
        }
        VolcengineVideoTask volcengineVideoTask = this.getById(dataBean.getTask_id());
        if (volcengineVideoTask == null) {
            throw new CustException("任务不存在");
        }
        if(!"failed".equals(dataBean.getStatus())) {
            throw new CustException("只有失败状态可进行重试");
        }

        List<CreateContentGenerationTaskRequest.Content> contents = new ArrayList<>();

        // 图生视频功能 构建请求参数
        // 文本提示词与参数组合
        if (StringUtils.isBlank(volcengineVideoTask.getText())) {
            volcengineVideoTask.setText("");
        }
        StringBuilder text = new StringBuilder(volcengineVideoTask.getText());
        if(StringUtils.isNotBlank(volcengineVideoTask.getResolution())) {
            text.append(" --rs ").append(volcengineVideoTask.getResolution());
        }
        if(volcengineVideoTask.getDuration() != null) {
            text.append(" --dur ").append(volcengineVideoTask.getDuration());
        }
        if(volcengineVideoTask.getCamerafixed() != null) {
            if (volcengineVideoTask.getCamerafixed() == 1) {
                text.append(" --cf true");
            } else {
                text.append(" --cf false");
            }
        }

        contents.add(CreateContentGenerationTaskRequest.Content.builder()
                .type("text")
                .text(text.toString())
                .build());


        // 首帧图片 (若仅需使用文本生成视频功能，可将此部分内容进行注释处理。)
        contents.add(CreateContentGenerationTaskRequest.Content.builder()
                .type("image_url")
                .imageUrl(CreateContentGenerationTaskRequest.ImageUrl.builder()
                        .url(volcengineVideoTask.getImg_url())
                        .build())
                .build());

        String notifyUrl = domain+ "/api/ai/volcengine/video/notify";
        // 创建视频生成任务
        CreateContentGenerationTaskRequest createRequest = CreateContentGenerationTaskRequest.builder()
                .model(volcengineVideoTask.getModel())
                .content(contents)
                // 回调地址
                .callbackUrl(notifyUrl)
                .build();

        dataBean.setUser_id(volcengineVideoTaskDetail.getUser_id());
        dataBean.setStatus("queued");
        // 创建图生视频任务
        CreateContentGenerationTaskResult taskResult = service.createContentGenerationTask(createRequest);

        dataBean.setVolcengine_task_id(taskResult.getId());

        volcengineVideoTaskDetailService.updateById(dataBean);

        return dataBean;

    }

    @Override
    public void notify(VolcengineVideoTaskNotify notify) {

        VolcengineVideoTaskDetail dataBean = volcengineVideoTaskDetailService.getOne(Wrappers.<VolcengineVideoTaskDetail>lambdaQuery()
                .eq(VolcengineVideoTaskDetail::getVolcengine_task_id, notify.getId()));
        if (dataBean == null) {
            // 任务状态排队/运行中，可能速度快于平台数据库保存，可忽略，其他状态视为异常
            if(!Arrays.asList("queued","running").contains(notify.getStatus())){
                log.error("图生视频通知异常，找不到任务明细，通知内容：" + notify);
                throw new CustException("图生视频通知异常，找不到任务明细");
            } else {
                return;
            }
        }

        if("succeeded".equals(dataBean.getStatus()) || "failed".equals(dataBean.getStatus())) {
            // 任务已经完成，不再处理
            return;
        }

        // 任务状态
        dataBean.setStatus(notify.getStatus());

        if(notify.getSeed() != null) {
            dataBean.setSeed(notify.getSeed());
        }

        if("succeeded".equals(notify.getStatus())) {
            // 成功
            String videoOriginUrl = notify.getContent().getVideoUrl();
            dataBean.setVideo_origin_url(videoOriginUrl);

            // URL转存文件
            SysFileResult sysFileResult = sysFileService.urlToUploadFile(videoOriginUrl, dataBean.getUser_id());
            String objectKey = sysFileResult.getKey();
            String videoUrl = sysFileResult.getDomain() + "/" + sysFileResult.getKey();
            dataBean.setVideo_url(videoUrl);
            dataBean.setObject_key(objectKey);
        } else {
            if(notify.getError() !=null) {
                dataBean.setError_msg(notify.getError().toString());
            }
        }
        // 更新任务信息
        volcengineVideoTaskDetailService.updateById(dataBean);
    }
}
