package com.hz.pm.api.scheduler.task;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.staging.contants.StagingContant;
import com.hz.pm.api.staging.model.entity.ProjectStaging;
import com.hz.pm.api.staging.service.IProjectStagingService;
import com.hz.pm.api.staging.utils.ProjectStatusFlowMapUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

/**
 * @Classname ProjectStatusFlowTask
 * @Description
 * @Date 2023/2/20 10:12
 * @Author PoffyZhang
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ProjectStatusFlowTask {

    private final IProjectStagingService projectStagingService;

    private final IProjectService projectService;
    
    @Value("${hostname}")
    private String HOST_NAME;

    @Scheduled(cron = "0 */1 * * * ?")
    public void statusFlow() throws UnknownHostException {
        if (HOST_NAME.equals(InetAddress.getLocalHost().getHostName())) {
            //1. 定时取 项目暂存表的数据 去进行状态继续流转
            List<ProjectStaging> stagingList = projectStagingService.list(Wrappers.lambdaQuery(ProjectStaging.class)
                    .eq(ProjectStaging::getDead, Boolean.FALSE)
                    .le(ProjectStaging::getNextTime, LocalDateTime.now())
                    .le(ProjectStaging::getRetryTimes, StagingContant.Retry.MAX_RETRY_TIMES)
                    .orderByAsc(ProjectStaging::getProjectId));

            log.info("需要状态流转的项目 size:{} :{}", stagingList.size(), JSON.toJSONString(stagingList));
            if (CollUtil.isEmpty(stagingList)) {
                log.info("没有需要状态流转的项目!");
                return;
            }

            //遍历
            for (ProjectStaging projectStaging : stagingList) {
                try {
                    Project project = projectService.getById(projectStaging.getProjectId());
                    if (Objects.isNull(project)) {
                        log.info("此项目 【{}】 不存在", projectStaging.getProjectId());
                        continue;
                    }
                    //2. 用函数map 定位到 状态流转的函数
                    Function<Project, Boolean> flowFunction = ProjectStatusFlowMapUtil.getFlowFunction(project.getStatus());
                    if (flowFunction == null) {
                        log.info("此项目 【{}】 当前状态 【{}】,没有对应流转函数", projectStaging.getProjectId(), project.getStatus());
                        continue;
                    }
                    //执行对应的函数
                    if (flowFunction.apply(project)) {
                        //执行成功了 删除暂存的数据
                        projectStagingService.removeById(projectStaging);
                    }
                } catch (Exception e) {
                    log.error("项目流转 异常 projectId:【" + projectStaging.getProjectId() + "】 异常内容:" + e.getMessage());
                } finally {
                    //增加重试的次数 和下次扫描时间
                    projectStagingService.addRetryTimes(projectStaging);
                }
            }
        }
    }

}
