package com.ai.da.service.impl;

import com.ai.da.common.constant.CommonConstant;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.response.PageBaseResponse;
import com.ai.da.common.utils.MinioUtil;
import com.ai.da.common.utils.RedisUtil;
import com.ai.da.mapper.primary.TaskListMapper;
import com.ai.da.mapper.primary.entity.TaskList;
import com.ai.da.model.dto.QueryTaskHistoryDTO;
import com.ai.da.model.dto.SuperResolutionDTO;
import com.ai.da.model.dto.TaskDTO;
import com.ai.da.model.vo.TaskVO;
import com.ai.da.service.SuperResolutionService;
import com.ai.da.service.TaskListService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Type;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class TaskListServiceImpl extends ServiceImpl<TaskListMapper, TaskList> implements TaskListService {

    @Resource
    private RedisUtil redisUtil;

    @Value("${redis.key.taskList}")
    private String taskListKey;

    @Resource
    private MinioUtil minioUtil;

    @Resource
    private SuperResolutionService superResolutionService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TaskDTO<SuperResolutionDTO>> getExecTask(List<String> taskIdList) {
        Long id = UserContext.getUserHolder().getId();
//        Set<String> keys = redisUtil.getKeysFromString(taskListKey + ":" + id + ":*");
        ArrayList<TaskDTO<SuperResolutionDTO>> taskDTOS = new ArrayList<>();
        taskIdList.forEach(taskId -> {
            String taskDetail = redisUtil.getFromString(taskListKey + ":" + id + ":" + taskId);
            Gson gson = new Gson();
            Type type = new TypeToken<TaskDTO<SuperResolutionDTO>>() {
            }.getType();
            TaskDTO<SuperResolutionDTO> taskDTO = gson.fromJson(taskDetail, type);
            if (Objects.isNull(taskDTO)) {
                // 未执行成功的taskId在redis被删除，将该条数据在db中的状态改为失败
                superResolutionService.updateSROutput(taskId, "fail", null);
                taskDTOS.add(new TaskDTO<>());
            } else {
                SuperResolutionDTO inputParam = taskDTO.getInputParam();
                inputParam.setImages(minioUtil.getPreSignedUrl(inputParam.getImages(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
                taskDTO.setOutputImage(StringUtil.isNullOrEmpty(taskDTO.getOutputImage()) ? null : minioUtil.getPreSignedUrl(taskDTO.getOutputImage(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
                taskDTOS.add(taskDTO);
            }
        });
        return taskDTOS;
    }

    public void addToTaskListRedis(TaskDTO<SuperResolutionDTO> taskDTO) {
        String key = taskListKey + ":" + UserContext.getUserHolder().getId() + ":" + taskDTO.getTaskId();
        redisUtil.addToString(key, new Gson().toJson(taskDTO), CommonConstant.TASK_EXPIRE_TIME);
    }

    // 3、更新任务状态
    @Override
    public void updateTaskStatusOrOutputRedis(String taskId, String status, String output) {
        String key = taskListKey + ":" + taskId.substring(taskId.lastIndexOf("-") + 1) + ":" + taskId;
        String taskDetail = redisUtil.getFromString(key);
        Gson gson = new Gson();
        Type type = new TypeToken<TaskDTO<SuperResolutionDTO>>() {
        }.getType();
        TaskDTO<SuperResolutionDTO> taskDTO = gson.fromJson(taskDetail, type);
        taskDTO.setStatus(status);
        if (!StringUtil.isNullOrEmpty(output)) {
            taskDTO.setOutputImage(output);
        }
        Long expire = redisUtil.getExpire(key);
        redisUtil.addToString(key, new Gson().toJson(taskDTO), expire);
    }

    @Override
    public PageBaseResponse<TaskVO> getAllTask(QueryTaskHistoryDTO queryTaskHistoryDTO) {
        PageBaseResponse<TaskVO> response = new PageBaseResponse<>();
        ArrayList<TaskVO> taskLists = new ArrayList<>();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        switch (queryTaskHistoryDTO.getType()) {
            case "SR":
                PageBaseResponse<TaskList> taskHistoryPage = superResolutionService.getTaskHistoryPage(queryTaskHistoryDTO);
                List<TaskList> srHistory = taskHistoryPage.getContent();
                srHistory.forEach(s -> {
                    // 成功失败的都返回
                    TaskVO task = new TaskVO();
                    task.setImageName(s.getInputUrl().substring(s.getInputUrl().lastIndexOf("/") + 1));
                    task.setInputImage(minioUtil.getPreSignedUrl(s.getInputUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
                    task.setOutputImage(StringUtil.isNullOrEmpty(s.getOutputUrl()) ? null : minioUtil.getPreSignedUrl(s.getOutputUrl(), CommonConstant.MINIO_IMAGE_EXPIRE_TIME));
                    task.setStatus(s.getStatus());
                    task.setTaskId(s.getTaskId());
                    task.setCreateDate(s.getCreateTime().format(dateTimeFormatter));
                    task.setOtherInput("×" + s.getScale());
                    taskLists.add(task);
                });
                BeanUtils.copyProperties(taskHistoryPage, response);
                response.setContent(taskLists);
                break;
            case "GENERATE":
                log.info("未知任务类型--GENERATE");
        }
        return response;
    }
}
