/**
 * 
 */
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.DsyJob;
import org.springblade.etl.entity.DsyJobInstance;
import org.springblade.etl.enums.InstanceStatus;
import org.springblade.etl.service.DsyJobInstanceService;
import org.springblade.etl.service.DsyJobService;
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;

/**
 *	数据同步任务实例 操作处理
 *
 * @author aokunsang
 * @date   2023-09-21
 */
@RestController
@RequestMapping("/dsy-job-instance")
@Api(value = "数据同步任务实例相关接口", tags = "数据同步任务实例接口")
public class DsyJobInstanceController extends BladeController {

	@Autowired
	private DsyJobInstanceService dsyJobInstanceService;
	
	@Autowired
	private DsyJobService dsyJobService;
	
	@Autowired
	private DataPermClient dataPermClient;
	
	/**
	 * 	列表数据
	 * @param dsyJobInstance
	 * @return
	 */
	@GetMapping("/merge-page")
	@ApiOperation(value = "分页查询任务分组聚合实例", httpMethod = "GET")
	public R<IPage<DsyJobInstance>> mergePageList(DsyJobInstance dsyJobInstance, Query query){
		LambdaQueryWrapper<DsyJobInstance> queryWrapper = Wrappers.<DsyJobInstance>lambdaQuery().orderByDesc(DsyJobInstance::getId);
		if(dsyJobInstance.getStartTime() != null && dsyJobInstance.getEndTime() != null) {
			queryWrapper
			.gt(DsyJobInstance::getCreateTime, DateUtil.format(dsyJobInstance.getStartTime(), "yyyy-MM-dd"))
			.lt(DsyJobInstance::getCreateTime, DateUtil.format(dsyJobInstance.getEndTime(), "yyyy-MM-dd"));
		}
		queryWrapper.eq(DsyJobInstance::getTenantId, AuthUtil.getTenantId())
					.eq(dsyJobInstance.getJobId() != null, DsyJobInstance::getJobId, dsyJobInstance.getJobId())
					.eq(dsyJobInstance.getInstanceType() != null, DsyJobInstance::getInstanceType, dsyJobInstance.getInstanceType())
					.eq(dsyJobInstance.getInstanceRunType() != null, DsyJobInstance::getInstanceRunType, dsyJobInstance.getInstanceRunType())
					.eq(dsyJobInstance.getInstanceStatus() != null, DsyJobInstance::getInstanceStatus, dsyJobInstance.getInstanceStatus());
		
		Long userId = getUser().getUserId();
		Boolean checkSuperPermRet = dataPermClient.checkSuperPermission(userId);
		if(checkSuperPermRet == null || !checkSuperPermRet) {
			List<Integer> jobIdList = dsyJobService.jobIdListOfPerm(userId);
			if(CollectionUtil.isEmpty(jobIdList)) {
				return R.data(new Page<DsyJobInstance>());
			}
			queryWrapper.in(DsyJobInstance::getJobId, jobIdList);
		}
		LambdaQueryWrapper<DsyJobInstance> _queryWrapper = queryWrapper.clone();
		IPage<DsyJobInstance> instancePage = dsyJobInstanceService.customPage(((Page)Condition.getPage(query)).setSearchCount(false), queryWrapper.groupBy(DsyJobInstance::getJobId));
		if(instancePage != null && CollectionUtil.isNotEmpty(instancePage.getRecords())) {
			Long totalCnt = dsyJobInstanceService.countPage(_queryWrapper);
			instancePage.setTotal(totalCnt == null ? 0L : totalCnt);
			instancePage.getRecords().forEach(item -> {
				DsyJob job = dsyJobService.getById(item.getJobId());
				DsyJobInstance _jobInstance = dsyJobInstanceService.getById(item.getId());
				InstanceStatusCount instanceStatusCount = dsyJobInstanceService.statInstanceStatusByJobId(item.getJobId());
				item.setJobName(job == null ? "[已删除]" : job.getJobName());
				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 dsyJobInstance
	 * @return
	 */
	@GetMapping("/page")
	@ApiOperation(value = "分页根据任务ID查询任务实例", httpMethod = "GET")
	public R<IPage<DsyJobInstance>> pageList(DsyJobInstance dsyJobInstance, Query query){
		LambdaQueryWrapper<DsyJobInstance> queryWrapper = Condition.getQueryWrapper(dsyJobInstance).lambda().orderByDesc(DsyJobInstance::getId);
		if(dsyJobInstance.getStartTime() != null && dsyJobInstance.getEndTime() != null) {
			queryWrapper
			.gt(DsyJobInstance::getCreateTime, DateUtil.format(dsyJobInstance.getStartTime(), "yyyy-MM-dd"))
			.lt(DsyJobInstance::getCreateTime, DateUtil.format(dsyJobInstance.getEndTime(), "yyyy-MM-dd"));
		}
		Long userId = getUser().getUserId();
		Boolean checkSuperPermRet = dataPermClient.checkSuperPermission(userId);
		if(checkSuperPermRet == null || !checkSuperPermRet) {
			List<Integer> jobIdList = dsyJobService.jobIdListOfPerm(userId);
			if(CollectionUtil.isEmpty(jobIdList)) {
				return R.data(new Page<DsyJobInstance>());
			}
			queryWrapper.in(DsyJobInstance::getJobId, jobIdList);
		}
		IPage<DsyJobInstance> instancePage = dsyJobInstanceService.page(Condition.getPage(query), queryWrapper);
		if(instancePage != null && CollectionUtil.isNotEmpty(instancePage.getRecords())) {
			instancePage.getRecords().forEach(item -> {
				DsyJob job = dsyJobService.getById(item.getJobId());
				item.setJobName(job == null ? "[已删除]" : job.getJobName());
			});
		}
		return R.data(instancePage);
	}
	
	/**
	 * 单条数据查询接口
	 * @param id
	 * @return
	 */
	@GetMapping("/info")
	@ApiOperation(value = "根据ID获取数据同步任务实例", httpMethod = "GET")
	public R<DsyJobInstance> info(@RequestParam Integer id) {
		return R.data(dsyJobInstanceService.getById(id));
	}
	
	/**
	 * 	删除数据接口
	 * @param id
	 * @return
	 */
	@ApiLog("数据同步任务实例")
	@PostMapping("/delete")
	@ApiOperation(value = "根据ID删除数据同步任务实例", httpMethod = "POST")
	public R<String> doDelete(@RequestParam Integer id) {
		DsyJobInstance dbJobInstance = dsyJobInstanceService.getById(id);
		if(dbJobInstance.getInstanceStatus() == InstanceStatus.RUNNING) {
			return R.fail("实例运行中，不能删除");
		}
		return R.status(dsyJobInstanceService.removeById(id));
	}
	
	/**
	 * 
	 * @param jobInstanceId
	 * @return
	 * @throws Exception 
	 */
	@ApiLog("数据同步任务实例")
	@PostMapping("/cancel")
	@ApiOperation(value = "根据ID取消/暂停任务实例", httpMethod = "POST")
	public R<String> doCancel(Integer jobInstanceId) throws Exception {
		dsyJobInstanceService.cancelJobInstance(jobInstanceId);
		return R.success("任务已取消");
	}
	
	/**
	 * 
	 * @return
	 */
	@PostMapping("/stat")
	@ApiOperation(value = "任务运行状态的统计", httpMethod = "POST")
	public R<List<JobStatRes>> stat(@RequestBody JobStatReq jobStatReq){
		List<JobStatRes> resList = dsyJobInstanceService.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);
	}
}