package cn.iocoder.yudao.module.smartfactory.service.screendata;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Month;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.smartfactory.controller.admin.screendata.factory.vo.*;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factorydata.FactoryDataDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factorydataoverview.FactoryDataOverviewDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factoryinfo.FactoryInfoDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.packagedata.PackageDataDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.screenfactoryextra.ScreenFactoryExtraDO;
import cn.iocoder.yudao.module.smartfactory.dal.mysql.factorydataoverview.FactoryDataOverviewMapper;
import cn.iocoder.yudao.module.smartfactory.framework.util.HttpUtil;
import cn.iocoder.yudao.module.smartfactory.service.factorydata.FactoryDataService;
import cn.iocoder.yudao.module.smartfactory.service.factorydataoverview.FactoryDataOverviewService;
import cn.iocoder.yudao.module.smartfactory.service.factoryinfo.FactoryInfoService;
import cn.iocoder.yudao.module.smartfactory.service.packagedata.PackageDataService;
import cn.iocoder.yudao.module.smartfactory.service.screenfactoryextra.ScreenFactoryExtraService;
import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能描述
 *
 * @author: yj
 * @date: 2024年03月06日 11:54
 */
@Service
@Validated
public class ScreenDataServiceImpl implements ScreenDataService {
    @Resource
    private FactoryInfoService factoryInfoService;
    @Resource
    private ScreenFactoryExtraService screenFactoryExtraService;
    @Resource
    private StaffService staffService;
    @Resource
    private PackageDataService packageDataService;
    @Resource
    private FactoryDataService factoryDataService;
    @Resource
    private FactoryDataOverviewService factoryDataOverviewService;
    @Resource
    private FactoryDataOverviewMapper factoryDataOverviewMapper;

    @Override
    public List<ProvincesDataRespVO> getProvincesData(String code) {
        return factoryInfoService.getProvincesData(code);
    }

    @Override
    public StaffDataRespVO getStaffData(Long factoryId) {
        return staffService.getStaffData(factoryId);
    }

    @Override
    public PropertyDataRespVO getPropertyData(Long factoryId) {
        return screenFactoryExtraService.getPropertyData(factoryId);
    }

    @Override
    public OperateDataRespVO getFactoryOperateData(Long factoryId) {
        return null;
    }

    @Override
    public List<FactoryRollDataRespVO> getFactoryRollData() {
        return factoryInfoService.getFactoryRollData();
    }

    @Override
    public List<FactoryCameraDataRespVO> getFactoryCamerasData(Long factoryId) {
        return null;
    }


    private static final String WEATHER_URL = "https://d1.weather.com.cn/sk_2d/";
    private static final String REFERER = "referer";
    private static final String REFERER_URL = "http://www.weather.com.cn/";
    private static final String WEATHER_SPLIT = "dataSK=";

    @Override
    public FactoryWeatherDataRespVO getFactoryWeatherInfo(Long factoryId) {
        //根据factoryId 查询areaCode;
        // 通过工厂id获取到天气数据code
        FactoryInfoDO factoryInfoDO = factoryInfoService.getFactoryInfo(factoryId);
        if (factoryInfoDO != null) {
            String areaCode = "";
            if (factoryInfoDO.getAdCode() != null) {
                areaCode = factoryInfoService.getWeatherCodeByFactoryId(factoryId, String.valueOf(factoryInfoDO.getAdCode()));
            } else if (StrUtil.isEmpty(areaCode)) {
                areaCode = factoryInfoService.getWeatherCodeByFactoryId(factoryId, String.valueOf(factoryInfoDO.getCityId()));
            } else if (StrUtil.isEmpty(areaCode)) {
                areaCode = factoryInfoService.getWeatherCodeByFactoryId(factoryId, String.valueOf(factoryInfoDO.getProvinceId()));
            } else {
                return null;
            }
            String url = WEATHER_URL + areaCode + ".html";
            Map<String, String> headers = new HashMap<>();
            headers.put(REFERER, REFERER_URL);
            String result = HttpUtil.doGetSetHeader(url, headers);
            String[] str = result.split(WEATHER_SPLIT);
            if (str.length > 1) {
                FactoryWeatherDataRespVO vo = new FactoryWeatherDataRespVO();
                JSONObject jsonObject = JSONUtil.parseObj(str[1]);
                vo.setFactoryId(factoryId);
                vo.setAreaCode(areaCode);
                vo.setTemperature(jsonObject.getStr("temp")); //温度
                vo.setHumidity(jsonObject.getStr("sd"));       //湿度
                vo.setWeather(jsonObject.getStr("weather"));  //天气
                vo.setDate(jsonObject.getStr("date"));         //日期
                return vo;
            } else {
                return null;
            }
        }
        return null;
    }

    @Override
    public List<FactoryPackLineInfoVO> getFactoryPackLineInfo(Long factoryId) {
        List<FactoryPackLineInfoVO> vos = new ArrayList<>();
        List<PackageDataDO> list = packageDataService.getFactoryPackLineInfo(factoryId);
        Map<Long, List<PackageDataDO>> map = list.stream().collect(Collectors.groupingBy(PackageDataDO::getSizeId));
        Date today = new Date();
        //本日打包数
        Date beginDay = DateUtil.beginOfDay(today);
        Date endDay = DateUtil.endOfDay(today);
        List<PackageDataDO> todayList = packageDataService.getFactoryPackLineInfoByTime(factoryId, beginDay, endDay);
        Map<Long, List<PackageDataDO>> todayMap = todayList.stream().collect(Collectors.groupingBy(PackageDataDO::getSizeId));
        //本周打包數
        Date beginWeek = DateUtil.beginOfWeek(today);
        Date endWeek = DateUtil.endOfWeek(today);
        List<PackageDataDO> weekList = packageDataService.getFactoryPackLineInfoByTime(factoryId, beginWeek, endWeek);
        Map<Long, List<PackageDataDO>> weekMap = weekList.stream().collect(Collectors.groupingBy(PackageDataDO::getSizeId));

        //本月打包數
        Date beginMonth = DateUtil.beginOfMonth(today);
        Date endMonth = DateUtil.endOfMonth(today);
        List<PackageDataDO> monthList = packageDataService.getFactoryPackLineInfoByTime(factoryId, beginMonth, endMonth);
        Map<Long, List<PackageDataDO>> monthMap = monthList.stream().collect(Collectors.groupingBy(PackageDataDO::getSizeId));

        for (Long id : map.keySet()) {
            PackageDataDO item = map.get(id).get(0);
            FactoryPackLineInfoVO vo = new FactoryPackLineInfoVO();
            vo.setId(item.getSizeId());
            vo.setName(item.getSizeName());
            List<PackageDataDO> todayItemList = todayMap.get(item.getSizeId());
            if (!CollUtil.isEmpty(todayItemList)) {
                vo.setDayNum(todayItemList.stream().mapToInt(PackageDataDO::getNum).sum());
            }
            List<PackageDataDO> weekItemList = weekMap.get(item.getSizeId());
            if (!CollUtil.isEmpty(weekItemList)) {
                vo.setWeekNum(weekItemList.stream().mapToInt(PackageDataDO::getNum).sum());
            }
            List<PackageDataDO> monthItemList = monthMap.get(item.getSizeId());
            if (!CollUtil.isEmpty(monthItemList)) {
                vo.setMonthNum(monthItemList.stream().mapToInt(PackageDataDO::getNum).sum());
            }
            vos.add(vo);
        }
        return vos;
    }

    @Override
    public String getAliYunGeo(String code, Integer type) {
        String url = "";
        if (type == 1) {
            url = "https://geo.datav.aliyun.com/areas_v3/bound/%s_full.json";
        } else {
            url = "https://geo.datav.aliyun.com/areas_v3/bound/%s.json";
        }
        url = String.format(url, code);
        return cn.hutool.http.HttpUtil.get(url);
    }

    @Override
    public DataOverviewVO getDataOverview() {
        DataOverviewVO vo = new DataOverviewVO();
        List<ScreenFactoryExtraDO> extras = screenFactoryExtraService.list();
        List<FactoryDataOverviewDO> list = factoryDataOverviewService.list();

        vo.setTotal(list.stream().mapToInt(FactoryDataOverviewDO::getWorkerNum).sum());
        vo.setYlNum(extras.stream().mapToInt(ScreenFactoryExtraDO::getYlNum).sum());
        vo.setForkliftTotal(list.stream().mapToInt(FactoryDataOverviewDO::getTruckTotalNum).sum());
        vo.setTruckOnNum(extras.stream().mapToInt(ScreenFactoryExtraDO::getTruckOnNum).sum());
        vo.setTruckOffNum(extras.stream().mapToInt(ScreenFactoryExtraDO::getTruckOffNum).sum());
        vo.setDbxNum(list.stream().mapToInt(FactoryDataOverviewDO::getDbxNum).sum());

        vo.setTpNum(list.stream().mapToInt(FactoryDataOverviewDO::getTpNum).sum());
        vo.setBdNum(list.stream().mapToInt(FactoryDataOverviewDO::getBdNum).sum());

        List<FactoryDataDO> factoryDataDOS = factoryDataService.getTodayInboundAndOutboundOverview(null);
        Integer outTotalNum = factoryDataDOS.stream().filter(a -> a.getDataType() == 1).mapToInt(FactoryDataDO::getTotalNum).sum();
        Integer inTotalNum = factoryDataDOS.stream().filter(a -> a.getDataType() == 2).mapToInt(FactoryDataDO::getTotalNum).sum();
        vo.setOutTotalNum(outTotalNum);
        vo.setInTotalNum(inTotalNum);
        return vo;
    }

    @Override
    public List<InboundAndOutboundOverviewVO> getInboundAndOutboundOverview() {
        List<InboundAndOutboundOverviewVO> vos = new ArrayList<>();
        //获取当天的所有数据
        List<FactoryDataDO> list = factoryDataService.getTodayInboundAndOutboundOverview(new Date());
        //根据工厂分组
        Map<Long, List<FactoryDataDO>> map = list.stream().collect(Collectors.groupingBy(FactoryDataDO::getFactoryId));
        List<FactoryInfoDO> factoryInfos = factoryInfoService.list();
        Map<Long, List<FactoryInfoDO>> factoryInfoMap = factoryInfos.stream().collect(Collectors.groupingBy(FactoryInfoDO::getId));
        for (Map.Entry<Long, List<FactoryDataDO>> entry : map.entrySet()) {
            List<FactoryDataDO> items = entry.getValue();
            Integer outTotalNum = items.stream().filter(a -> a.getDataType() == 1).mapToInt(FactoryDataDO::getTotalNum).sum();
            Integer inTotalNum = items.stream().filter(a -> a.getDataType() == 2).mapToInt(FactoryDataDO::getTotalNum).sum();
            List<FactoryInfoDO> itemDo = factoryInfoMap.get(entry.getKey());
            if (!CollUtil.isEmpty(itemDo)) {
                InboundAndOutboundOverviewVO vo = new InboundAndOutboundOverviewVO();
                vo.setName(itemDo.get(0).getShortName());
                vo.setOutTotalNum(outTotalNum);
                vo.setInTotalNum(inTotalNum);
                vos.add(vo);
            }
        }
        // -- list排序
        vos = vos.stream()
                .sorted(Comparator.comparingInt(InboundAndOutboundOverviewVO::getInTotalNum).reversed())
                .collect(Collectors.toList());
        return vos;
    }

    @Override
    public List<ExcellentRateRankingVO> excellentRateRanking() {
        List<ExcellentRateRankingVO> list = new ArrayList<>();
        List<FactoryInfoDO> factoryInfos = factoryInfoService.list();
        for (FactoryInfoDO factoryInfo : factoryInfos) {
            // 创建 Random 对象
            Random random = new Random();
            // 生成 90 到 100 之间的随机数（包括 90 和 100）
            double randomNumber = random.nextDouble() * 11 + 85;
            // 将随机数保留两位小数
            randomNumber = Math.round(randomNumber * 100.0) / 100.0;
            if (randomNumber > 100) {
                randomNumber = 100.00;
            }
            ExcellentRateRankingVO vo = new ExcellentRateRankingVO();
            vo.setName(factoryInfo.getName());
            vo.setExcellentRate(randomNumber);
            list.add(vo);
        }
        // -- list排序
        list = list.stream()
                .sorted(Comparator.comparingDouble(ExcellentRateRankingVO::getExcellentRate).reversed())
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public List<EnergyConservationVO> energyConservation(Long factoryId) {
        List<EnergyConservationVO> vos = new ArrayList<>();
        List<FactoryInfoDO> factoryInfos = factoryInfoService.list();
        List<Long> ids = factoryInfos.stream().map(FactoryInfoDO::getId).collect(Collectors.toList());
        List<FactoryDataOverviewDO> dos = factoryDataOverviewMapper.selectList(new LambdaQueryWrapperX<FactoryDataOverviewDO>()
                .in(FactoryDataOverviewDO::getFactoryId, ids));
        Map<Long, List<FactoryDataOverviewDO>> doMaps = dos.stream().collect(Collectors.groupingBy(FactoryDataOverviewDO::getFactoryId));
        if (factoryId != null) {
            Map<Long, List<FactoryInfoDO>> map = factoryInfos.stream().collect(Collectors.groupingBy(FactoryInfoDO::getId));
            List<FactoryInfoDO> items = map.get(factoryId);
            if (!CollUtil.isEmpty(items)) {
                for (int i = 0; i < 3; i++) {
                    Month month = DateUtil.monthEnum(DateUtil.offsetMonth(DateUtil.date(), -i));
                    EnergyConservationVO vo = new EnergyConservationVO();
                    vo.setName(items.get(0).getShortName());
                    vo.setTime((month.getValue() == 0 ? "12" : String.valueOf(month.getValue())) + "月");
                    Random random = new Random();
                    // 生成50到100之间的随机数
                    int randomNumber = random.nextInt(51) + 50;
                    vo.setEmissions(randomNumber);
                    List<FactoryDataOverviewDO> doItems = doMaps.get(items.get(0).getId());
                    if (CollUtil.isNotEmpty(doItems)) {
                        vo.setForkliftTotal(doItems.get(0).getTruckTotalNum());
                    } else {
                        vo.setForkliftTotal(0);
                    }
                    vos.add(vo);
                }
            }
        } else {
            for (FactoryInfoDO factoryInfo : factoryInfos) {
                EnergyConservationVO vo = new EnergyConservationVO();
                vo.setName(factoryInfo.getShortName());
                //vo.setTime(String.valueOf(factoryInfo.getValue()));
                Random random = new Random();
                // 生成50到100之间的随机数
                int randomNumber = random.nextInt(51) + 50;
                vo.setEmissions(randomNumber);
                List<FactoryDataOverviewDO> doItems = doMaps.get(factoryInfo.getId());
                if (CollUtil.isNotEmpty(doItems) && doItems.get(0).getTruckTotalNum() != null && doItems.get(0).getTruckTotalNum() > 0) {
                    vo.setForkliftTotal(doItems.get(0).getTruckTotalNum());
                    vos.add(vo);
                }
            }
        }
        Collections.reverse(vos);
        return vos;
    }

    @Override
    public ObtainFactoryInboundAndOutboundStatusVO getObtainFactoryInboundAndOutboundStatus(Long factoryId) {
        ObtainFactoryInboundAndOutboundStatusVO vo = new ObtainFactoryInboundAndOutboundStatusVO();

        Date today = new Date();
        //本日打包数
        Date beginDay = DateUtil.beginOfDay(today);
        Date endDay = DateUtil.endOfDay(today);

        List<FactoryDataDO> dayList = factoryDataService.getByTimeAndFactoryId(factoryId, beginDay, endDay);
        Integer outTotalNum = dayList.stream().filter(a -> a.getDataType() == 1).mapToInt(FactoryDataDO::getTotalNum).sum();
        Integer inTotalNum = dayList.stream().filter(a -> a.getDataType() == 2).mapToInt(FactoryDataDO::getTotalNum).sum();
        vo.setOutToday(outTotalNum);
        vo.setInToday(inTotalNum);

        //本月打包數
        Date beginMonth = DateUtil.beginOfMonth(today);
        Date endMonth = DateUtil.endOfMonth(today);
        List<FactoryDataDO> monthList = factoryDataService.getByTimeAndFactoryId(factoryId, beginMonth, endMonth);
        Integer outMonthNum = monthList.stream().filter(a -> a.getDataType() == 1).mapToInt(FactoryDataDO::getTotalNum).sum();
        Integer inMonthNum = monthList.stream().filter(a -> a.getDataType() == 2).mapToInt(FactoryDataDO::getTotalNum).sum();
        vo.setOutMonth(outMonthNum);
        vo.setInMonth(inMonthNum);
        Random random = new Random();
        int randomNumber = random.nextInt(21); // 生成0到20之间的随机数
        vo.setDamagedTotal(randomNumber);

        random = new Random();
        double increaseCompared = (random.nextDouble() * 4) - 2; // 生成-2到2之间的随机数
        increaseCompared = Math.round(increaseCompared * 100.0) / 100.0; // 保留两位小数
        vo.setIncreaseCompared(increaseCompared);
        return vo;
    }
}
