/**
 * 
 */
package org.springblade.etl.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.etl.dto.InstanceStatusCount;
import org.springblade.etl.dto.etl.JobStatReq;
import org.springblade.etl.dto.etl.JobStatRes;
import org.springblade.etl.entity.SqlJob;
import org.springblade.etl.entity.SqlJobInstance;
import org.springblade.etl.entity.SqlJobScript;
import org.springblade.etl.enums.InstanceStatus;
import org.springblade.etl.service.SqlJobInstanceService;
import org.springblade.etl.service.SqlJobScriptService;
import org.springblade.etl.service.SqlJobService;
import org.springblade.system.client.DataPermClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.hutool.core.date.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 *	SQL任务实例 操作处理
 *
 * @author aokunsang
 * @date   2023-12-03
 */
@RestController
@RequestMapping("/sqljob-instance")
@Api(value = "SQL任务实例相关接口", tags = "SQL任务实例接口")
public class SqlJobInstanceController extends BladeController {

	@Autowired
	private SqlJobInstanceService sqlJobInstanceService;
	
	@Autowired
	private SqlJobScriptService sqlJobScriptService;
	
	@Autowired
	private SqlJobService sqlJobService;
	
	@Autowired
	private DataPermClient dataPermClient;
	
	/**
	 * 	列表数据
	 * @param sqlJobInstance
	 * @return
	 */
	@GetMapping("/merge-page")
	@ApiOperation(value = "分页查询任务分组聚合实例", httpMethod = "GET")
	public R<IPage<SqlJobInstance>> mergePageList(SqlJobInstance sqlJobInstance, Query query){
		LambdaQueryWrapper<SqlJobInstance> queryWrapper = Wrappers.<SqlJobInstance>lambdaQuery().orderByDesc(SqlJobInstance::getId);
		if(sqlJobInstance.getStartTime() != null && sqlJobInstance.getEndTime() != null) {
			queryWrapper
			.gt(SqlJobInstance::getCreateTime, DateUtil.format(sqlJobInstance.getStartTime(), "yyyy-MM-dd"))
			.lt(SqlJobInstance::getCreateTime, DateUtil.format(sqlJobInstance.getEndTime(), "yyyy-MM-dd"));
		}
		queryWrapper.eq(SqlJobInstance::getTenantId, AuthUtil.getTenantId())
					.eq(sqlJobInstance.getJobId() != null, SqlJobInstance::getJobId, sqlJobInstance.getJobId())
					.eq(sqlJobInstance.getInstanceRunType() != null, SqlJobInstance::getInstanceRunType, sqlJobInstance.getInstanceRunType());
		
		Long userId = getUser().getUserId();
		Boolean checkSuperPermRet = dataPermClient.checkSuperPermission(userId);
		if(checkSuperPermRet == null || !checkSuperPermRet) {
			List<Integer> jobIdList = sqlJobService.jobIdListOfPerm(userId);
			if(CollectionUtil.isEmpty(jobIdList)) {
				return R.data(new Page<SqlJobInstance>());
			}
			queryWrapper.in(SqlJobInstance::getJobId, jobIdList);
		}
		LambdaQueryWrapper<SqlJobInstance> _queryWrapper = queryWrapper.clone();
		IPage<SqlJobInstance> instancePage = sqlJobInstanceService.customPage(((Page)Condition.getPage(query)).setSearchCount(false), queryWrapper.groupBy(SqlJobInstance::getJobId));
		if(instancePage != null && CollectionUtil.isNotEmpty(instancePage.getRecords())) {
			Long totalCnt = sqlJobInstanceService.countPage(_queryWrapper);
			instancePage.setTotal(totalCnt == null ? 0L : totalCnt);
			instancePage.getRecords().forEach(item -> {
				SqlJobScript jobScript = sqlJobScriptService.getById(item.getJobScriptId());
				SqlJobInstance _jobInstance = sqlJobInstanceService.getById(item.getId());
				SqlJob sqlJob = sqlJobService.getById(item.getJobId());
				InstanceStatusCount instanceStatusCount = sqlJobInstanceService.statInstanceStatusByJobId(item.getJobId());
				item.setJobName(sqlJob == null ? "[已删除]" : sqlJob.getJobName());
				item.setSqlScriptName(jobScript == null ? "[已删除]" : jobScript.getSqlScriptName());
				InstanceStatus instanceStatus = instanceStatusCount.getInstanceStatus();
				item.setInstanceStatus(instanceStatusCount != null ? instanceStatus : null);
				item.setInstanceRunType(_jobInstance.getInstanceRunType());
				if(instanceStatus == InstanceStatus.WAITING || instanceStatus == InstanceStatus.RUNNING) {
					item.setEndTime(null);
				}
			});
		}
		return R.data(instancePage);
	}
	
	/**
	 * 	列表数据
	 * @param sqlJobInstance
	 * @return
	 */
	@GetMapping("/page")
	@ApiOperation(value = "分页查询SQL任务实例", httpMethod = "GET")
	public R<IPage<SqlJobInstance>> pageList(SqlJobInstance sqlJobInstance, Query query){
		LambdaQueryWrapper<SqlJobInstance> queryWrapper = Condition.getQueryWrapper(sqlJobInstance).lambda().orderByDesc(SqlJobInstance::getId);
		if(sqlJobInstance.getStartTime() != null && sqlJobInstance.getEndTime() != null) {
			queryWrapper.gt(SqlJobInstance::getCreateTime, DateUtil.format(sqlJobInstance.getStartTime(), "yyyy-MM-dd"))
			.lt(SqlJobInstance::getCreateTime, DateUtil.format(sqlJobInstance.getEndTime(), "yyyy-MM-dd"));
		}
		Long userId = getUser().getUserId();
		Boolean checkSuperPermRet = dataPermClient.checkSuperPermission(userId);
		if(checkSuperPermRet == null || !checkSuperPermRet) {
			List<Integer> jobIdList = sqlJobService.jobIdListOfPerm(userId);
			if(CollectionUtil.isEmpty(jobIdList)) {
				return R.data(new Page<SqlJobInstance>());
			}
			queryWrapper.in(SqlJobInstance::getJobId, jobIdList);
		}
		IPage<SqlJobInstance> instancePage = sqlJobInstanceService.page(Condition.getPage(query), queryWrapper);
		if(instancePage != null && CollectionUtil.isNotEmpty(instancePage.getRecords())) {
			instancePage.getRecords().forEach(item -> {
				SqlJobScript jobScript = sqlJobScriptService.getById(item.getJobScriptId());
				SqlJob sqlJob = sqlJobService.getById(item.getJobId());
				item.setSqlScriptName(jobScript == null ? "[已删除]" : jobScript.getSqlScriptName());
				item.setJobName(sqlJob == null ? "[已删除]" : sqlJob.getJobName());
			});
		}
		return R.data(instancePage);
	}
	
	/**
	 * 单条数据查询接口
	 * @param id
	 * @return
	 */
	@GetMapping("/info")
	@ApiOperation(value = "根据ID获取SQL任务实例", httpMethod = "GET")
	public R<SqlJobInstance> info(@RequestParam Integer id) {
		return R.data(sqlJobInstanceService.getById(id));
	}
	
	/**
	 * 	删除数据接口
	 * @param id
	 * @return
	 */
	@ApiLog("SQL任务实例")
	@PostMapping("/delete")
	@ApiOperation(value = "根据ID删除SQL任务实例", httpMethod = "POST")
	public R<String> doDelete(@RequestParam Integer id) {
		SqlJobInstance dbJobInstance = sqlJobInstanceService.getById(id);
		if(dbJobInstance.getInstanceStatus() == InstanceStatus.RUNNING) {
			return R.fail("实例运行中，不能删除");
		}
		return R.status(sqlJobInstanceService.removeById(id));
	}
	
	/**
	 * 
	 * @return
	 */
	@PostMapping("/stat")
	@ApiOperation(value = "任务运行状态的统计", httpMethod = "POST")
	public R<List<JobStatRes>> stat(@RequestBody JobStatReq jobStatReq){
		List<JobStatRes> resList = sqlJobInstanceService.stat(jobStatReq);
		Map<InstanceStatus, JobStatRes> resMap = new HashMap<>();
		if(CollectionUtil.isNotEmpty(resList)) {
			resList.forEach(item -> resMap.put(InstanceStatus.of(item.getStatus()), item));
		}
		List<JobStatRes> dataList = new ArrayList<>(); 
		Stream.of(InstanceStatus.values()).forEach(item -> {
			JobStatRes jobStatRes = resMap.get(item);
			if(jobStatRes != null) {
				dataList.add(jobStatRes);
			}else {
				dataList.add(new JobStatRes(0L, item));
			}
		});
		return R.data(dataList);
	}
}