package cn.cecep.talroad.service.strategy;

import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.domain.AmProblemFi;
import cn.cecep.talroad.domain.BasDevice;
import cn.cecep.talroad.domain.STaskYieldTrend;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisCement;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisCoal;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisCoke;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisConverter;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisFurnace;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisGlass;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisPower;
import cn.cecep.talroad.domain.analysis.SRaRealTimeAnalysisRubbish;
import cn.cecep.talroad.enums.ProblemTypeEnum;
import cn.cecep.talroad.enums.TimeTypeEnum;
import cn.cecep.talroad.enums.YieldTypeEnum;
import cn.cecep.talroad.service.IAmProblemFiService;
import cn.cecep.talroad.service.IBasDeviceService;
import cn.cecep.talroad.service.STaskYieldTrendService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisCementService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisCoalService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisCokeService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisConverterService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisFurnaceService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisGlassService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisPowerService;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisRubbishService;
import cn.cecep.talroad.vo.FactoryDeviceVo;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @Auther: cjh
 * @Date: 2023-04-27 15:54
 * @Class: YieldStrategyAdapter
 * @Deseription:
 * @Version V1.0
 */
public abstract class YieldStrategyAdapter extends AbstractStrategyAdapter {

    @Autowired
    private IBasDeviceService basDeviceService;
    @Autowired
    private ISRaRealTimeAnalysisCoalService raRealTimeAnalysisCoalService;
    @Autowired
    private ISRaRealTimeAnalysisCokeService raRealTimeAnalysisCokeService;
    @Autowired
    private STaskYieldTrendService taskYieldTrendService;
    @Autowired
    private ISRaRealTimeAnalysisFurnaceService raRealTimeAnalysisFurnaceService;
    @Autowired
    private ISRaRealTimeAnalysisConverterService raRealTimeAnalysisConverterService;
    @Autowired
    private ISRaRealTimeAnalysisGlassService raRealTimeAnalysisGlassService;
    @Autowired
    private ISRaRealTimeAnalysisPowerService raRealTimeAnalysisPowerService;
    @Autowired
    private ISRaRealTimeAnalysisRubbishService raRealTimeAnalysisRubbishService;
    @Autowired
    private ISRaRealTimeAnalysisCementService raRealTimeAnalysisCementService;
    @Autowired
    private IAmProblemFiService amProblemFiService;

    @Override
    protected void doProcess(String industry, String deviceType, Date tempDate) {}

    @Override
    protected void doProcessYield(FactoryDeviceVo vo) {
        Date curr = new Date();
        this.doQueryYieldData(vo,curr,false);
    }

    @Override
    protected void doProcessYieldTemp(String factoryId, String industry, String deviceType, Date tempDate) {
        QueryWrapper<BasDevice> deviceQueryWrapper = new QueryWrapper<>();
        deviceQueryWrapper.select("device_id");
        deviceQueryWrapper.eq("factory_id", factoryId);
        deviceQueryWrapper.eq("industry", industry);
        deviceQueryWrapper.eq("type", deviceType);
        deviceQueryWrapper.eq("status", 1);
        List<BasDevice> deviceList = basDeviceService.list(deviceQueryWrapper);
        if (deviceList != null && deviceList.size() > 0) {
            // 查询设备类型的参数配置
            deviceList.forEach(d -> {
                FactoryDeviceVo vo = basDeviceService.selectFactoryDeviceVoByDeviceId(d.getDeviceId());
                // 计算产量
                this.doQueryYieldData(vo,tempDate,true);
            });
        }
    }

    /**
     * 处理产量统计逻辑
     * @param vo
     * @param tempDate
     * @param flag
     */
    protected abstract void doQueryYieldData(FactoryDeviceVo vo,Date tempDate,boolean flag);

    /**
     * 批量保存更新
     * @param list
     */
    protected void doSaveBatchYieldTrendData(List<STaskYieldTrend> list){
        if(list!=null&&list.size()>0){
            taskYieldTrendService.saveOrUpdateBatch(list);
        }
    }

    /**
     * 保存产量
     */
    protected void doSaveYieldTrendData(STaskYieldTrend trend){
        taskYieldTrendService.saveOrUpdate(trend);
    }

    /**
     * 查询是否已经生成报警数据
     * @return
     */
    protected boolean isExistAlarmData(FactoryDeviceVo vo,ProblemTypeEnum problemType,int hours){
        QueryWrapper<AmProblemFi> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("factory_id",vo.getFactoryId());
        queryWrapper.eq("device_id",vo.getDeviceId());
        queryWrapper.eq("problem_type",problemType.getCode());
        queryWrapper.gt("create_time",DateUtils.addDateHours(new Date(),-hours));
        List<AmProblemFi> list = amProblemFiService.list(queryWrapper);
        if(list!=null&&list.size()>0){
            return true;
        }
        return false;
    }

    /**
     * 处理报警数据
     * @param factoryId
     * @param deviceId
     * @param deviceName
     * @param start
     * @param end
     * @param problemType
     * @param msg
     */
    protected AmProblemFi doProcessAlaram(String factoryId,String deviceId,String deviceName, Date start, Date end, ProblemTypeEnum problemType, String msg,String param ,String paramProperty) {
        AmProblemFi problemFi = new AmProblemFi();
        problemFi.setProblemSources("1");
        problemFi.setFactoryId(factoryId);
        problemFi.setProblemDetails(msg);
        problemFi.setType(1);
        // 数据缺失专有字段
        if(problemType.getCode().equals(ProblemTypeEnum.SJQS.getCode())) {
            problemFi.setDeviceName(deviceName);
        }
        problemFi.setProblemType(problemType.getCode());
        problemFi.setProblemTreatmentState("1");
        problemFi.setAnalyseTime(start);
        problemFi.setAnalyseTimeEnd(end);
        problemFi.setStationId(deviceId);
        problemFi.setStationName(deviceName);
        problemFi.setCreateTime(new Date());
        problemFi.setParamName(param);
        problemFi.setParamProperty(paramProperty);
        Map<String,Object> map = new HashMap<>();
        List<Map<String,Object>> list = new ArrayList<>();
        Map m = new HashMap();
        m.put("deviceId",deviceId);
        m.put("params", Arrays.asList(paramProperty.split(",")));
        list.add(m);
        map.put("dcsDeviceList",list);
        problemFi.setExtra(JSON.toJSONString(map));
        return problemFi;
    }

    /**
     * 保存出铁量趋势
     * @param factoryId
     * @param deviceId
     * @param yieldTypeEnum 产量类型编码
     * @param lastHourBegin
     * @param currentCount
     * @param flag 是否处理历史数据  true 是 false 否
     */
    protected STaskYieldTrend doBuildTrenData(String factoryId,String deviceId,YieldTypeEnum yieldTypeEnum, Date lastHourBegin, BigDecimal currentCount,boolean flag) {
        STaskYieldTrend trend = new STaskYieldTrend();
        trend.setFactoryId(factoryId);
        trend.setDeviceId(deviceId);
        trend.setNumber(currentCount);
        trend.setDataTime(lastHourBegin);
        trend.setDictCode(yieldTypeEnum.getCode());
        trend.setTimeType(TimeTypeEnum.HOUR.getCode());
        if(!flag) {
            trend.setCreateTime(new Date());
            return trend;
        }else{
            QueryWrapper<STaskYieldTrend> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("factory_id",trend.getFactoryId());
            queryWrapper.eq("device_id",trend.getDeviceId());
            queryWrapper.eq("data_time",trend.getDataTime());
            queryWrapper.eq("dict_code",trend.getDictCode());
            queryWrapper.eq("time_type",trend.getTimeType());
            STaskYieldTrend oldTrend = taskYieldTrendService.getOne(queryWrapper);
            //存在产量数据则更新
            if(oldTrend!=null){
                oldTrend.setNumber(trend.getNumber());
                return oldTrend;
            }else{
                trend.setCreateTime(new Date());
                return trend;
            }
        }
    }

    /**
     * 保存出铁量数据
     * @param vo
     * @param lastTwoHourBegin
     * @param currentCount
     */
    protected void doSaveAnalysisFurnaceData(FactoryDeviceVo vo, Date lastTwoHourBegin, BigDecimal currentCount) {
        SRaRealTimeAnalysisFurnace furnace = new SRaRealTimeAnalysisFurnace();
        furnace.setFactoryId(vo.getFactoryId());
        furnace.setDeviceId(vo.getDeviceId());
        furnace.setFactoryName(vo.getFactoryName());
        furnace.setDistrictCode(vo.getCityCode());
        furnace.setDistrictName(vo.getCityName());
        furnace.setDeviceName(vo.getDeviceName());
        furnace.setAnalyseTime(lastTwoHourBegin);
        furnace.setTapNumber(currentCount);
        furnace.setCreateTime(new Date());
        raRealTimeAnalysisFurnaceService.save(furnace);
    }

    /**
     * 保存转炉产量
     * @param vo
     * @param gcrl
     * @param ls
     * @param cgl
     * @param analyseTime
     * @param cl
     */
    protected void doSaveAnalysisConverterData(FactoryDeviceVo vo, Double gcrl,long ls, Double cgl, Date analyseTime, BigDecimal cl) {
        SRaRealTimeAnalysisConverter s = new SRaRealTimeAnalysisConverter();
        s.setFactoryId(vo.getFactoryId());
        s.setFactoryName(vo.getFactoryName());
        s.setDistrictCode(vo.getCityCode());
        s.setDistrictName(vo.getCityName());
        s.setIndustryCategoryCode(vo.getIndustry());
        s.setIndustryCategoryName(vo.getIndustryName());
        s.setDeviceId(vo.getDeviceId());
        s.setDeviceName(vo.getDeviceName());
        s.setOutputNumber(cl);
        s.setNominalNumber(new BigDecimal(gcrl));
        s.setAnalyseTime(analyseTime);
        s.setConverterNumber(ls);
        s.setTapNumber(new BigDecimal(cgl));
        s.setCreateTime(new Date());
        raRealTimeAnalysisConverterService.save(s);
    }


    /**
     * 保存钢铁焦化焦炉产量
     * @param vo
     * @param tmcs
     * @param analyseTime
     * @param cl
     * @param yxrj
     */
    protected void doSaveAnalysisCokeData(FactoryDeviceVo vo, long tmcs, Date analyseTime,
        BigDecimal cl, AtomicReference<Double> yxrj) {
        // 计算焦炉产量
        SRaRealTimeAnalysisCoke coke = new SRaRealTimeAnalysisCoke();
        coke.setFactoryId(vo.getFactoryId());
        coke.setFactoryName(vo.getFactoryName());
        coke.setDistrictCode(vo.getCityCode());
        coke.setDistrictName(vo.getCityName());
        coke.setDeviceName(vo.getDeviceName());
        coke.setDeviceId(vo.getDeviceId());
        coke.setAnalyseTime(analyseTime);
        coke.setPushNumber(tmcs);
        coke.setCokeNumber(cl);
        coke.setVolumeNumber(new BigDecimal(yxrj.get()));
        coke.setCreateTime(new Date());
        raRealTimeAnalysisCokeService.save(coke);
    }

    /**
     * 保存装煤次数、推焦次数
     * @param vo
     * @param zmcs
     * @param tmcs
     * @param analyseTime
     */
    protected void doSaveAnalysisCoal(FactoryDeviceVo vo, long zmcs, long tmcs,
        Date analyseTime) {
        SRaRealTimeAnalysisCoal real = new SRaRealTimeAnalysisCoal();
        real.setCoalNumber(zmcs);
        real.setCokeNumber(tmcs);
        real.setFactoryName(vo.getFactoryName());
        real.setDistrictCode(vo.getCityCode());
        real.setDistrictName(vo.getCityName());
        real.setIndustryCategoryCode(vo.getIndustry());
        real.setIndustryCategoryName(vo.getIndustryName());
        real.setDeviceName(vo.getDeviceName());
        real.setAnalyseTime(analyseTime);
        real.setFactoryId(vo.getFactoryId());
        real.setDeviceId(vo.getDeviceId());
        real.setDataId(UUID.randomUUID().toString());
        real.setCreateTime(new Date());
        raRealTimeAnalysisCoalService.save(real);
    }

    /**
     * 保存玻璃产量数据
     * @param vo
     * @param curr
     * @param avgHour
     * @param edcs
     * @param sjcn
     * @param blcl
     */
    protected void doSaveAnalysisGlassData(FactoryDeviceVo vo, Date curr, Double avgHour,
        AtomicReference<Double> edcs, AtomicReference<Double> sjcn, BigDecimal blcl) {
        SRaRealTimeAnalysisGlass glass = new SRaRealTimeAnalysisGlass();
        glass.setGlassNumber(blcl);
        glass.setFactoryName(vo.getFactoryName());
        glass.setDistrictCode(vo.getCityCode());
        glass.setDistrictName(vo.getCityName());
        glass.setDeviceName(vo.getDeviceName());
        glass.setFactoryId(vo.getFactoryId());
        glass.setDeviceId(vo.getDeviceId());
        glass.setPlanNumber(new BigDecimal(sjcn.get()));
        glass.setKilnNumber(new BigDecimal(avgHour));
        glass.setRatedNumber(new BigDecimal(edcs.get()));
        glass.setAnalyseTime(DateUtils.parseFormatDate("yyyy-MM-dd HH:00:00", curr));
        glass.setCreateTime(new Date());
        raRealTimeAnalysisGlassService.save(glass);
    }

    /**
     * 保存电力机组负荷数据
     * @param vo
     * @param curr
     * @param avgHour
     */
    protected void doSaveAnalysisPowerData(FactoryDeviceVo vo, Date curr, Double avgHour) {
        SRaRealTimeAnalysisPower power = new SRaRealTimeAnalysisPower();
        power.setFactoryId(vo.getFactoryId());
        power.setFactoryName(vo.getFactoryName());
        power.setDistrictCode(vo.getCityCode());
        power.setDistrictName(vo.getCityName());
        power.setDeviceName(vo.getDeviceName());
        power.setDeviceId(vo.getDeviceId());
        power.setAnalyseTime(DateUtils.parseFormatDate("yyyy-MM-dd HH:00:00", curr));
        power.setPowerNumber(new BigDecimal(avgHour));
        power.setCreateTime(new Date());
        raRealTimeAnalysisPowerService.save(power);
    }


    /**
     * 保存垃圾处理量记录
     * @param vo
     * @param lastHour
     * @param currentValue
     * @param method
     */
    protected void doSaveRubbishData(FactoryDeviceVo vo, Date lastHour,
        BigDecimal currentValue, String method) {
        SRaRealTimeAnalysisRubbish rubbish = new SRaRealTimeAnalysisRubbish();
        rubbish.setRubbishNumber(currentValue);
        rubbish.setFeedingMethod(method);
        rubbish.setAnalyseTime(DateUtils.parseFormatDate("yyyy-MM-dd HH", lastHour));
        rubbish.setFactoryId(vo.getFactoryId());
        rubbish.setDeviceId(vo.getDeviceId());
        rubbish.setFactoryName(vo.getFactoryName());
        rubbish.setDistrictCode(vo.getCityCode());
        rubbish.setDistrictName(vo.getCityName());
        rubbish.setDeviceName(vo.getDeviceName());
        rubbish.setCreateTime(new Date());
        raRealTimeAnalysisRubbishService.save(rubbish);
    }

    /**
     * 保存水泥产量
     * @param vo
     * @param avgHour
     * @param slHour
     * @param analyseTime
     */
    protected void doSaveAnalysisCementData(FactoryDeviceVo vo, Double avgHour, BigDecimal slHour,
        Date analyseTime) {
        SRaRealTimeAnalysisCement real = new SRaRealTimeAnalysisCement();
        real.setAnalyseTime(analyseTime);
        real.setFactoryId( vo.getFactoryId());
        real.setFactoryName(vo.getFactoryName());
        real.setDistrictCode(vo.getCityCode());
        real.setDistrictName(vo.getCityName());
        real.setDeviceName(vo.getDeviceName());
        real.setDeviceId(vo.getDeviceId());
        real.setDeviceType(vo.getDeviceType());
        real.setAddNumber(new BigDecimal(avgHour));
        real.setGrogNumber(slHour);
        real.setCreateTime(new Date());
        raRealTimeAnalysisCementService.save(real);
    }

    /**
     * 批量保存报警数据
     * @param problemFi
     */
    protected void doSaveAlarm(AmProblemFi problemFi){
        amProblemFiService.save(problemFi);
    }

    /**
     * 批量保存报警数据
     * @param list
     */
    protected void doSaveBatchAlarm(List<AmProblemFi> list){
        if(list!=null&&list.size()>0) {
            amProblemFiService.saveBatch(list);
        }
    }
}
