package org.springblade.modules.nh.api;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.compress.utils.Lists;
import org.springblade.common.cache.DictCache;
import org.springblade.common.constant.NhConstants;
import org.springblade.common.enums.DictEnum;
import org.springblade.common.utils.CommonUtil;
import org.springblade.common.utils.TaskControl;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.nh.factory.ginlong.scheduler.GinlongStationMonthEachRunner;
import org.springblade.modules.nh.factory.goodwe.scheduler.GoodweStationFisGenDateEachRunner;
import org.springblade.modules.nh.factory.goodwe.scheduler.GoodweStationMonthEachRunner;
import org.springblade.modules.nh.factory.goodwe.scheduler.GoodweStationYearEachRunner;
import org.springblade.modules.nh.job.InefficientScheduler;
import org.springblade.modules.nh.pojo.dto.DeviceDTO;
import org.springblade.modules.nh.pojo.dto.MonitorEntryStatDTO;
import org.springblade.modules.nh.pojo.dto.PowerStationDTO;
import org.springblade.modules.nh.pojo.entity.InefficientSettingEntity;
import org.springblade.modules.nh.pojo.entity.MonitorEntryStatEntity;
import org.springblade.modules.nh.pojo.entity.PowerStationEntity;
import org.springblade.modules.nh.pojo.entity.PowerStationInefficientEntity;
import org.springblade.modules.nh.pojo.vo.MonitorEntryStatVO;
import org.springblade.modules.nh.service.*;
import org.springblade.modules.nh.wrapper.MonitorEntryStatWrapper;
import org.springblade.modules.nh.wrapper.PowerStationWrapper;
import org.springframework.web.bind.annotation.*;
import scala.collection.mutable.StringBuilder;

import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 设备管理 控制器
 *
 * @author AlexWang
 * @since 2024-05-31
 */
@RestController
@AllArgsConstructor
@RequestMapping("nat/open")
@Tag(name = "设备管理", description = "设备管理接口")
public class NatOpenSyncController extends BladeController {

	private final IPowerStationService stationService;

	private final IMonitorEntryStatService entryStatService;

	private final BladeRedis bladeRedis;

	private final GoodweStationMonthEachRunner goodweStationMonthEachRunner;
	private final GinlongStationMonthEachRunner ginlongStationMonthEachRunner;
	private final GoodweStationFisGenDateEachRunner stationFisGenDateEachRunner;

	private final IInefficientSettingService settingService;
	private final InefficientScheduler inefficientScheduler;

	private final GoodweStationYearEachRunner goodweStationYearEachRunner;

	/**
	 * 计算平均发电时间
	 */
	@GetMapping(value = "syncEntryYearData")
	@Operation(summary = "同步固德威电站年数据")
	public R syncEntryYearData(String stationCode,int year){
		checkRunState("syncEntryYearData"+stationCode);
		PowerStationEntity entity = stationService.getStationDetailByPowCode(stationCode);
		if(entity==null){
			return R.fail("不存在编码为：《"+stationCode+"》的电站");
		}

		if(!NhConstants.SYS_TYPE_GOODWE.equals(entity.getBrand()+"")){
			return R.fail("不是固德威的电站");
		}

		MonitorEntryStatEntity entryStat = entryStatService.getByOutId(entity.getOutStationId());
		if(entryStat==null){
			return R.fail("不存在编码为：《"+stationCode+"》的外部电站");
		}
		List<List<String>> partitions = ListUtils.partition(Collections.singletonList(entryStat.getOutStationId()), 50);
		Map<String,Object> ctx = CommonUtil.getCtx(entryStat.getVendorIndex());
		ctx.put("year",year);
		goodweStationYearEachRunner.start(partitions, "获取单个电站年的数据", 0L, ctx);

		return R.success("同步固德威电站年数据 执行成功");
	}

	/**
	 * 计算平均发电时间
	 */
	@GetMapping(value = "updateEntryYearData")
	@Operation(summary = "更新固德威电站年数据")
	public R updateEntryYearData(String stationCode,int year){
		checkRunState("updateEntryYearData"+stationCode);
		PowerStationEntity entity = stationService.getStationDetailByPowCode(stationCode);
		if(entity==null){
			return R.fail("不存在编码为：《"+stationCode+"》的电站");
		}

		if(!NhConstants.SYS_TYPE_GOODWE.equals(entity.getBrand()+"")){
			return R.fail("不是固德威的电站");
		}

		MonitorEntryStatEntity entryStat = entryStatService.getByOutId(entity.getOutStationId());
		if(entryStat==null){
			return R.fail("不存在编码为：《"+stationCode+"》的外部电站");
		}
		LocalDate today = LocalDate.now();
		int currentYear = today.getYear();
		int currentMonth = today.getMonthValue();
		entryStatService.updateEntryYearData(entryStat,currentYear,currentMonth);

		return R.success("更新固德威电站年数据 执行成功");
	}

	/**
	 * 计算平均发电时间
	 */
	@GetMapping(value = "calAvgPowerStationHours")
	@Operation(summary = "计算低效电站")
	public R calAvgPowerStationHours(String capitalName){
		checkRunState("calAvgPowerStationHours"+capitalName);
		inefficientScheduler.executeAvgHours();

		return R.success("计算低效电站平均发电时间 执行成功");
	}

	/**
	 * 计算低效电站
	 */
	@GetMapping(value = "calInefficientByStationCode")
	@Operation(summary = "计算低效电站")
	public R calInefficientByStationCode(String stationCode){
		PowerStationEntity entity = stationService.getStationDetailByPowCode(stationCode);
		if(entity==null){
			return R.fail("不存在编码为：《"+stationCode+"》的电站");
		}
		MonitorEntryStatEntity entryStat = entryStatService.getByOutId(entity.getOutStationId());
		if(entryStat==null){
			return R.fail("不存在编码为：《"+stationCode+"》的外部电站");
		}
//		checkRunState("calInefficientByStationCode："+stationCode);

		String planType = DictCache.getKey(DictEnum.SETTING_PLAN_TYPE,entity.getInstallType());

		LambdaQueryWrapper<InefficientSettingEntity> ew = new LambdaQueryWrapper<>();
		ew.eq(InefficientSettingEntity::getCapitalName,entity.getCapitalName())
			.eq(InefficientSettingEntity::getPlanType,planType)
			.like(InefficientSettingEntity::getCitys,"%"+entity.getCity().replaceAll("市","")+"%");
		InefficientSettingEntity setting = settingService.getOne(ew);

		PowerStationInefficientEntity ret = inefficientScheduler.calIneffiectStation(setting,entity,2);

		return R.data(ret);
	}

	/**
	 * 计算低效电站
	 */
	@GetMapping(value = "calInefficientPowerStation")
	@Operation(summary = "计算低效电站")
	public R calInefficientPowerStation(String capitalName){
		checkRunState("calAvgPowerStationHours"+capitalName);

		LambdaQueryWrapper<InefficientSettingEntity> ew = new LambdaQueryWrapper<>();
				ew.eq(InefficientSettingEntity::getCapitalName,capitalName);
		List<InefficientSettingEntity> settingList = settingService.list(ew);
		settingList.forEach(setting->{
			inefficientScheduler.calInefficientSetting(setting);
		});
		return R.success("执行成功");
	}

	/**
	 * 同步固德威的电站首日发电时间
	 */
	@GetMapping(value = "syncGoodweFisTime")
	@Operation(summary = "同步固德威的电站首日发电时间")
	public R syncGoodweFisTime(String stationCode){
		if(StringUtil.isBlank(stationCode)){
			return R.fail("电站编码不能为空");
		}
		checkRunState("sync_start_month_"+stationCode);
		PowerStationEntity entity = stationService.getStationDetailByPowCode(stationCode);
		if(entity==null){
			return R.fail("不存在编码为：《"+stationCode+"》的电站");
		}
		if(entity.getBrand()==null || StringUtil.isBlank(entity.getOutStationId())){
			return R.fail("不该电站品牌不存在或电站外部电站未关联");
		}
		if(NhConstants.SYS_TYPE_GOODWE.equals(entity.getBrand().toString())){
			MonitorEntryStatVO vo = entryStatService.getByPowerStation(PowerStationWrapper.build().entityVO(entity));
			List<String> ids = Collections.singletonList(vo.getOutStationId());
			goodweStationYearEachRunner.start(Collections.singletonList(ids), "获取单个电站某年的月数据", 0L, CommonUtil.getCtx(vo.getVendorIndex()));
			stationFisGenDateEachRunner.start(ids, "获取单个电站某月的日数据", 0L, CommonUtil.getCtx(vo.getVendorIndex()));
		}

		return R.success("同步固德威的电站首日发电时间 执行完毕");
	}

	/**
	 * 同步固德威的电站首日发电时间
	 */
	@GetMapping(value = "calAllGoodweFisTime")
	@Operation(summary = "计算全部的goodwe的首次发电时间")
	public R calAllGoodweFisTime(){
		checkRunState("CAL_ALL_GOODWE_FISTIME_ALL",60*60);

		TaskControl.runTask("goodwe:calAllGoodweFisTime", new Runnable() {
				@Override
				public void run() {
					for(int i=1;i<=3;i++){
						LambdaQueryWrapper<MonitorEntryStatEntity> queryWrapper = new LambdaQueryWrapper<>();
						queryWrapper.eq(MonitorEntryStatEntity::getType, NhConstants.SYS_TYPE_GOODWE)
							.in(MonitorEntryStatEntity::getState,2,3)
							.select(MonitorEntryStatEntity::getOutStationId)
							.eq(MonitorEntryStatEntity::getVendorIndex,i);
						List<String> stationIds = entryStatService.listObjs(queryWrapper);
						stationFisGenDateEachRunner.start(stationIds, "获取电站的首日发电时间", 12L, CommonUtil.getCtx(i));
					}
				}
		});


		return R.success("计算全部的goodwe的首次发电时间 执行完毕");
	}

	/**
	 * 同步日数据
	 */
	@GetMapping(value = "syncStationMonthData")
	@Operation(summary = "同步日数据")
	public R syncStationMonth(String stationCode,String month){
		if(StringUtil.isBlank(stationCode)){
			return R.fail("电站编码不能为空");
		}

		checkRunState("sync_start_month_"+stationCode);

		PowerStationEntity entity = stationService.getStationDetailByPowCode(stationCode);
		if(entity==null){
			return R.fail("不存在编码为：《"+stationCode+"》的电站");
		}
		if(entity.getBrand()==null || StringUtil.isBlank(entity.getOutStationId())){
			return R.fail("不该电站品牌不存在或电站外部电站未关联");
		}
		MonitorEntryStatVO vo = entryStatService.getByPowerStation(PowerStationWrapper.build().entityVO(entity));
		if(NhConstants.SYS_TYPE_GOODWE.equals(entity.getBrand().toString())){
			List<List<String>> partitions = ListUtils.partition(Collections.singletonList(vo.getOutStationId()), 50);
			goodweStationMonthEachRunner.start(partitions, "获取单个电站某月的日数据", 15L, CommonUtil.getCtx(vo.getVendorIndex()));
		}
		if(NhConstants.SYS_TYPE_GINLONG.equals(entity.getBrand().toString())){
			Map<String,Object> ctx = CommonUtil.getCtx(vo.getVendorIndex());
			ctx.put("month",month);
			ginlongStationMonthEachRunner.start(Collections.singletonList(vo.getOutStationId()), "获取单个电站某月的日数据", 2L, ctx);
		}

		return R.success("同步电站日数据 执行完毕");
	}


	private void checkRunState(String key){
		checkRunState(key,60L);
	}

	private void checkRunState(String key,long seconds){
		if(bladeRedis.exists(key)){
			throw new ServiceException("程序正在执行中，请耐心等待");
		}
		bladeRedis.setEx(key,"1",seconds);
	}
}
