package com.ycwl.basic.biz;

import com.ycwl.basic.mapper.FaceMapper;
import com.ycwl.basic.mapper.TaskMapper;
import com.ycwl.basic.mapper.VideoMapper;
import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.task.req.TaskReqQuery;
import com.ycwl.basic.model.pc.task.resp.TaskRespVO;
import com.ycwl.basic.model.pc.template.resp.TemplateRespVO;
import com.ycwl.basic.model.pc.video.entity.VideoEntity;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.TemplateRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Component
public class TaskStatusBiz {
    public static final String TASK_STATUS_USER_CACHE_KEY = "task:status:user:%s:face:%s";
    public static final String TASK_STATUS_FACE_CACHE_KEY = "task:status:face:%s";
    public static final String TASK_STATUS_FACE_CACHE_KEY_CUT = "task:status:face:%s:cut";
    public static final String TASK_STATUS_FACE_CACHE_KEY_TEMPLATE = "task:status:face:%s:tpl:%s";

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private FaceRepository faceRepository;
    @Autowired
    private TemplateRepository templateRepository;
    @Autowired
    private FaceMapper faceMapper;
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private TemplateBiz templateBiz;

    public boolean getUserHaveFace(Long userId, Long faceId) {
        if (userId == null || faceId == null) {
            return false;
        }
        if (redisTemplate.hasKey(String.format(TASK_STATUS_USER_CACHE_KEY, userId, faceId))) {
            return true;
        }
        FaceEntity face = faceRepository.getFace(faceId);
        if (face == null) {
            return false;
        }
        if (face.getMemberId().equals(userId)) {
            redisTemplate.opsForValue().set(String.format(TASK_STATUS_USER_CACHE_KEY, userId, faceId), "1", 3600, TimeUnit.SECONDS);
            return true;
        } else {
            return false;
        }
    }

    public void setFaceCutStatus(Long faceId, int status) {
        redisTemplate.opsForValue().set(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId), String.valueOf(status), 3600, TimeUnit.SECONDS);
    }

    public void setFaceTemplateStatus(Long faceId, Long templateId, Long videoId) {
        redisTemplate.opsForValue().set(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId), String.valueOf(videoId), 3600, TimeUnit.SECONDS);
    }

    public VideoTaskStatusVO getScenicUserStatus(Long scenicId, Long userId) {
        FaceRespVO lastFace = faceMapper.findLastFaceByScenicAndUserId(scenicId, userId);
        VideoTaskStatusVO response = new VideoTaskStatusVO();
        if (lastFace == null) {
            response.setStatus(-1);
            return response;
        }
        return getFaceStatus(lastFace.getId());
    }

    public VideoTaskStatusVO getFaceStatus(Long faceId) {
        FaceEntity face = faceRepository.getFace(faceId);
        VideoTaskStatusVO response = new VideoTaskStatusVO();
        if (face == null) {
            response.setStatus(-1);
            return response;
        }
        response.setScenicId(face.getScenicId());
        response.setFaceId(faceId);
        List<TemplateRespVO> templateList = templateRepository.getTemplateListByScenicId(face.getScenicId());
        response.setMaxCount(templateList.size());
        int alreadyFinished = 0;
        for (TemplateRespVO template : templateList) {
            response.setTemplateId(template.getId());
            long videoId = getFaceTemplateVideoId(faceId, template.getId());
            if (videoId <= 0) {
                response.setStatus(2);
            } else {
                response.setVideoId(videoId);
                alreadyFinished++;
            }
        }
        response.setCount(alreadyFinished);
        if (alreadyFinished == 0) {
            response.setStatus(0);
        } else {
            response.setStatus(1);
        }
        if (alreadyFinished == 0) {
            int faceCutStatus = getFaceCutStatus(faceId);
            if (faceCutStatus != 1) {
                // 正在切片
                if (templateBiz.determineTemplateCanGenerate(templateList.getFirst().getId(), faceId, false)) {
                    response.setStatus(2);
                } else {
                    response.setStatus(0);
                }
            }
        }
        return response;
    }

    public VideoTaskStatusVO getFaceTemplateStatus(Long faceId, Long templateId) {
        FaceEntity face = faceRepository.getFace(faceId);
        VideoTaskStatusVO response = new VideoTaskStatusVO();
        if (face == null) {
            response.setStatus(-1);
            return response;
        }
        response.setScenicId(face.getScenicId());
        response.setFaceId(faceId);
        response.setTemplateId(templateId);
        long videoId = getFaceTemplateVideoId(faceId, templateId);
        if (videoId < 0) {
            int faceCutStatus = getFaceCutStatus(faceId);
            if (faceCutStatus != 1) {
                // 正在切片
                response.setStatus(2);
                return response;
            }
        } else if (videoId == 0) {
            response.setStatus(2);
        } else {
            response.setVideoId(videoId);
            response.setStatus(1);
        }
        return response;
    }

    public int getFaceCutStatus(Long faceId) {
        if (redisTemplate.hasKey(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId))) {
            String status = redisTemplate.opsForValue().get(String.format(TASK_STATUS_FACE_CACHE_KEY_CUT, faceId));
            if (status != null) {
                return Integer.parseInt(status);
            }
        }
        return 1;
    }

    public long getFaceTemplateVideoId(Long faceId, Long templateId) {
        if (redisTemplate.hasKey(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId))) {
            String status = redisTemplate.opsForValue().get(String.format(TASK_STATUS_FACE_CACHE_KEY_TEMPLATE, faceId, templateId));
            if (status != null) {
                return Long.parseLong(status);
            }
        }
        TaskReqQuery taskReqQuery = new TaskReqQuery();
        taskReqQuery.setFaceId(faceId);
        taskReqQuery.setTemplateId(templateId);
        List<TaskRespVO> list = taskMapper.list(taskReqQuery);
        Optional<TaskRespVO> min = list.stream().min(Comparator.comparing(TaskRespVO::getCreateTime));
        if (min.isPresent()) {
            TaskRespVO task = min.get();
            long taskStatus = 0;
            if (task.getStatus() == 1) {
                // 已完成
                VideoEntity video = videoMapper.findByTaskId(task.getId());
                if (video != null) {
                    taskStatus = video.getId();
                }
            }
            setFaceTemplateStatus(faceId, templateId, taskStatus);
        } else {
            // 从来没生成过
            setFaceTemplateStatus(faceId, templateId, -1L);
            return -1;
        }
        return 0;
    }
}
