/*
 * 文 件 名:  WeatherColAmapServiceImpl
 * 版    权:
 * 描    述:  <描述>
 * 修 改 人:  learshaw
 * 修改时间:  2021/9/22
 * 跟踪单号:  <跟踪单号>
 * 修改单号:  <修改单号>
 * 修改内容:  <修改内容>
 */
package com.huashe.common.data.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huashe.common.data.config.JuheWeatherConfig;
import com.huashe.common.data.mapper.AdmWeatherForecastMapper;
import com.huashe.common.data.mapper.AdmWeatherRtMapper;
import com.huashe.common.data.service.RegionService;
import com.huashe.common.data.service.WeatherColService;
import com.huashe.common.domain.model.Region;
import com.huashe.common.domain.model.WeatherForecast;
import com.huashe.common.domain.model.WeatherRt;
import com.huashe.common.exception.Assert;
import com.huashe.common.utils.HttpUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 天气实时采集-聚合
 * <功能详细描述>
 *
 * @author learshaw
 * @version [版本号, 2021/9/22]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Service("weatherColJuheService")
@ConditionalOnProperty(prefix = "weather", name = "service-provider", havingValue = "juhe", matchIfMissing = false)
public class WeatherColJuheServiceImpl implements WeatherColService {
    private static final Logger log = LoggerFactory.getLogger(WeatherColJuheServiceImpl.class);

    /**
     * 系统配置
     */
    @Resource
    private JuheWeatherConfig config;

    @Resource
    private AdmWeatherRtMapper weatherRtMapper;

    @Resource
    private AdmWeatherForecastMapper weatherForecastMapper;

    @Value("${weather.region.conf-adcodes}")
    private String weatherAdcodes;

    /**
     * 区域映射装配
     */
    @Resource
    private RegionService regionService;

    /**
     * 天气采集
     */
    @Override
    public void collect() {
        try {
            List<Region> regions = getArea();

            for (Region region : regions) {
                colSingle(region);
            }
        }
        catch (Exception e) {
            log.error("collect weather fail!", e);
        }
    }

    public void colSingle(Region region) {
        try {
            String dfUrl = StringUtils.replace(config.getUrl(), "#{cityname}", region.getName());

            log.debug("get url:\r\n{}", dfUrl);
            String res = HttpUtils.doGet(dfUrl);
            log.debug("get res:\r\n{}", res);
            JSONObject resBody = JSON.parseObject(res);

            String code = resBody.getString("error_code");
            Assert.isTrue(StringUtils.equals(code, "0"), -1, resBody.getString("reason"));

            JSONObject result = resBody.getJSONObject("result");

            if (null != result) {
                JSONObject realtime = result.getJSONObject("realtime");

                if (null != realtime) {
                    WeatherRt weatherRt = convertRt(region, realtime);
                    weatherRtMapper.merge(weatherRt);
                }

                JSONArray future = result.getJSONArray("future");

                if (null != future) {
                    List<WeatherForecast> forecasts = convertForecast(region, future);
                    if (CollectionUtils.isNotEmpty(forecasts)) {
                        weatherForecastMapper.deleteByAdcode(region.getAdcode());
                        weatherForecastMapper.insertBatch(forecasts);
                    }
                    else {
                        weatherForecastMapper.deleteByAdcode(region.getAdcode());
                    }
                }
            }
        }
        catch (Exception e) {
            log.error("collectRt fail!", e);
        }
    }

    public List<Region> getArea() {
        List<Region> areas = new ArrayList<>();

        // 直辖市
        List<Region> municipalitys = regionService.getMunicipality();
        areas.addAll(municipalitys);

        // 省会城市
        Region param = new Region();
        param.setAreaType(2);
        List<Region> regions = regionService.getRegion(param);
        areas.addAll(regions);

        // 自定义城市
        String[] areaArray = StringUtils.split(weatherAdcodes, ",");

        if (ArrayUtils.isNotEmpty(areaArray)) {
            for (String areacode : areaArray) {
                Region region = regionService.getRegionByCode(areacode);
                areas.add(region);
            }
        }

        return areas;
    }

    private WeatherRt convertRt(Region region, JSONObject jsObj) {
        WeatherRt po = new WeatherRt();
        po.setAdcode(region.getAdcode());
        po.setAreaName(region.getName());
        po.setDate(new Date());

        String weather = jsObj.getString("info");
        po.setWeatherCn(weather);
        String weatherStr = StringUtils.contains(weather, "-") ? StringUtils.substringBefore(weather, "-") : weather;
        po.setWeatherType(config.getWeatherTypeByName(weatherStr));

        po.setTemperature(jsObj.getDouble("temperature"));
        po.setHumidity(jsObj.getInteger("humidity"));
        po.setWindPower(jsObj.getString("power"));
        po.setWindDirection(jsObj.getString("direct"));
        po.setReportTime(new Date());
        return po;
    }

    private List<WeatherForecast> convertForecast(Region region, JSONArray jsonArray) {
        Date date = new Date();
        List<WeatherForecast> forecastList = new ArrayList<>();

        jsonArray.forEach(item -> {
            JSONObject entity = (JSONObject) item;
            WeatherForecast forecast = new WeatherForecast();
            forecast.setAdcode(region.getAdcode());
            forecast.setAreaName(region.getName());
            forecast.setDate(entity.getDate("date"));

            String dayWeather = entity.getString("weather");
            forecast.setDayWeatherCn(dayWeather);
            String weatherStr = StringUtils.contains(dayWeather, "-") ?
                StringUtils.substringBefore(dayWeather, "-") :
                dayWeather;
            forecast.setDayWeatherType(config.getWeatherTypeByName(weatherStr));

            String nightWeather = entity.getString("dayWeather");
            forecast.setNightWeatherCn(nightWeather);
            String weatherStr2 = StringUtils.contains(nightWeather, "-") ?
                StringUtils.substringBefore(nightWeather, "-") :
                nightWeather;
            forecast.setNightWeatherType(config.getWeatherTypeByName(weatherStr2));

            String temp = entity.getString("temperature");

            forecast.setDayTemp(safeDouble(StringUtils.substringBetween(temp, "/", "℃")));
            forecast.setNightTemp(safeDouble(StringUtils.substringBefore(temp, "/")));
            forecast.setDayWindDir(entity.getString("direct"));
            forecast.setNightWindDir(entity.getString("direct"));
            forecast.setReportTime(date);
            forecastList.add(forecast);
        });

        return forecastList;
    }

    private Double safeDouble(String str) {
        Double ret = null;

        try {
            ret = Double.valueOf(str);
        }
        catch (Exception e) {
        }

        return ret;
    }
}