package com.iformall.service.kw.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.IdWorker;
import com.iformall.common.ResultData;

import com.iformall.domain.po.KwBox;
import com.iformall.domain.po.KwMeter;
import com.iformall.domain.po.KwMeterData;
import com.iformall.enums.*;
import com.iformall.mapper.KwBoxMapper;
import com.iformall.mapper.KwMeterMapper;
import com.iformall.service.kw.KwBoxService;
import com.iformall.service.kw.KwMeterDataService;
import com.iformall.service.kw.KwMeterService;
import io.netty.util.internal.StringUtil;
import org.apache.rocketmq.common.filter.impl.Op;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class KwBoxServiceImpl implements KwBoxService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    KwBoxMapper kwBoxMapper;

    @Autowired
    KwMeterDataService kwMeterDataService;

    @Autowired
    KwMeterService kwMeterService;

    @Autowired
    KwMeterMapper kwMeterMapper;


    @Override
    public PageInfo<KwBox> listAsPage(KwBox record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> kwBoxMapper.findList(record));
    }

    @Override
    public KwBox getById(Long id) {
        return kwBoxMapper.selectById(id);
    }


    @Override
    public void saveOrUpdate(KwBox record) {
        if (record.getId() == null) {
            final IdWorker idWorker = IdWorker.get();
        	record.setId(idWorker.nextId());
            record.setCreateTime(new Date());
            record.setUpdateTime(new Date());
            kwBoxMapper.insert(record);
        } else {
            record.setUpdateTime(new Date());
            kwBoxMapper.updateById(record);
        }
    }


    @Override
    public void deleteById(Long id) {
        kwBoxMapper.deleteById(id);
    }

    @Override
    public List<KwBox> findList(KwBox record) {
        return kwBoxMapper.findList(record);
    }

    @Override
    public KwBox findByImei(String imei) {
        KwBox kwBox = new KwBox();
        kwBox.setImei(imei);
        kwBox.setStatus(EnumBoxStatus.VALID.getCode());
        List<KwBox> kwBoxes = findList(kwBox);
        if (kwBoxes.size() > 0)
            return kwBoxes.get(0);
        return null;
    }

    @Override
    public void saveMeterData(KwBox kwBox, List<Map<String,String>> metersData, Date deviceTime){

        if (!metersData.isEmpty()) {

            List<KwMeter> kwMeterList = findMeters(kwBox);

            List<KwMeterData> kwMeterDataList = new ArrayList<>();
            Date recordTime = new Date();
            final IdWorker idWorker = IdWorker.get();
            metersData.stream().forEach(md->{
                String address = md.get(KwBoxService.METER_ADDRESS);
                String activePower = md.get(KwBoxService.METER_ACTIVE_POWER); //active power

                Optional<KwMeter> kwMeter = kwMeterList.stream().filter(m->m.getAddress().equals(address)).findAny();

                if (kwMeter.isPresent()) {
                    KwMeterData kwMeterData = new KwMeterData();

                    kwMeterData.setId(idWorker.nextId());
                    kwMeterData.setTenantId(kwBox.getTenantId());
                    kwMeterData.setAddress(address);
                    kwMeterData.setBoxId(kwBox.getId());
                    kwMeterData.setCreateTime(recordTime);
                    kwMeterData.setDeviceTime(deviceTime);
                    kwMeterData.setMeterId(kwMeter.get().getId());
                    if (!StringUtil.isNullOrEmpty(activePower)) {
                        kwMeterData.setTotalPower(Integer.parseInt(activePower));
                    }

                    kwMeterDataList.add(kwMeterData);
                }
            });


            List<KwMeter> onlineMeters = kwMeterDataList.stream().filter(md->md.getTotalPower()!=null)
                    .map( md->{
                        KwMeter kwMeter = new KwMeter();
                        kwMeter.setId(md.getMeterId());
                        kwMeter.setTotalPower(md.getTotalPower());
                        return kwMeter;
                    }).collect(Collectors.toList());
            if (onlineMeters.size() > 0) {
                kwMeterService.onlineBatch(onlineMeters);
            }

            List<Long> offlineIds = kwMeterDataList.stream().filter(md->md.getTotalPower()==null).map(KwMeterData::getMeterId).collect(Collectors.toList());
            if (offlineIds.size() > 0) {
                KwMeter kwMeter = new KwMeter();
                kwMeter.setIds(offlineIds);
                kwMeterService.offlineBatch(kwMeter);
            }


            List<Long> onlineIds = kwMeterDataList.stream().filter(md->md.getTotalPower()!=null)
                    .map(KwMeterData::getMeterId).collect(Collectors.toList());
            if (onlineIds.size() > 0) {
                KwMeterData param = new KwMeterData();
                param.setIds(onlineIds);
                List<KwMeterData> lastRecordList = kwMeterDataService.findLastRecordList(param);
                kwMeterDataList.stream().forEach(md->{
                    Optional<KwMeterData> data = lastRecordList.stream().filter(lr->lr.getMeterId().equals(md.getMeterId())).findAny();
                    if (data.isPresent()) {
                        md.setUsedPower(
                                md.getTotalPower()-data.get().getTotalPower());
                        md.setLastDeviceTime(data.get().getDeviceTime());
                        md.setLastTotalPower(data.get().getTotalPower());
                    }
                });
            }

            kwMeterDataService.save(kwMeterDataList);
        }
    }

    @Override
    public List<String> findMetersAddress(KwBox record) {

        List<KwMeter> kwMeters = findMeters(record);

        if (kwMeters.isEmpty()) {
            logger.info("没找到盒子关联的表: boxId=" + record.getId());
            return new ArrayList<>();
        }
        return kwMeters.stream().map(KwMeter::getAddress).collect(Collectors.toList());
    }

    @Override
    public List<KwMeter> findMeters(KwBox record) {

        KwMeter kwMeter = new KwMeter();
        kwMeter.setBoxId(record.getId());
        kwMeter.setBindStatus(EnumMeterBindStatus.BIND.getCode());
        kwMeter.setStatus(EnumMeterStatus.VALID.getCode());

        return kwMeterMapper.findList(kwMeter);
    }

}
