package com.kym.service.admin.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kym.common.enums.EnPlusApi;
import com.kym.common.utils.AESUtil;
import com.kym.entity.admin.EquipmentInfo;
import com.kym.entity.admin.Station;
import com.kym.entity.admin.vo.StationVo;
import com.kym.entity.enplus.EnEquipmentInfo;
import com.kym.entity.enplus.EnStationStatsInfo;
import com.kym.entity.enplus.EnStationStatusInfo;
import com.kym.mapper.admin.StationMapper;
import com.kym.service.admin.EquipmentInfoService;
import com.kym.service.admin.StationService;
import com.kym.service.enplus.EnPlusService;
import com.kym.service.utils.KymCache;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * <p>
 * 充电站信息 服务实现类
 * </p>
 *
 * @author skyline
 * @since 2023-08-12
 */
@Service
@DS("db-admin")
public class StationServiceImpl extends ServiceImpl<StationMapper, Station> implements StationService {

    private final KymCache kymCache;

    private final EquipmentInfoService equipmentInfoService;


    private final EnPlusService enPlusService;

    public StationServiceImpl(@Lazy KymCache kymCache, EnPlusService enPlusService, EquipmentInfoService equipmentInfoService) {
        this.kymCache = kymCache;
        this.enPlusService = enPlusService;
        this.equipmentInfoService = equipmentInfoService;
    }

    @Override
    public List<StationVo> queryStationInfo(int pageNum, int pageSize) {
        var param = """
                {
                    "PageNo":%d,
                    "PageSize":%d,
                    "LastQueryTime":""
                }
                """.formatted(pageNum, pageSize);
        var response = enPlusService.enPlusPost(EnPlusApi.EN_PLUS_QUERY_STATION_INFO.getApi(), enPlusService.buildParams(param));
        var enStations = JSONObject.parseObject(AESUtil.decrypt(response.getData()));
        var stationList = enStations.getJSONArray("StationInfos").toJavaList(StationVo.class);
        stationList.forEach(station -> station.getEquipmentInfos().forEach(enEquipmentInfo -> enEquipmentInfo.setShortId(kymCache.getShortId(enEquipmentInfo.getEquipmentId()))));
        stationList.forEach(vo -> vo.setEquipmentInfos(vo.getEquipmentInfos().stream().sorted(Comparator.comparing(EnEquipmentInfo::getShortId)).toList()));
        return stationList;

    }


    @Override
    public List<EnStationStatusInfo> stationStatus(String[] ids) {
        var param = """
                {
                    "StationIDs":["%s"]
                }
                """.formatted(String.join("\",\"", ids));
        var response = enPlusService.enPlusPost(EnPlusApi.EN_PLUS_QUERY_STATION_STATUS.getApi(), enPlusService.buildParams(param));
        var enStationStatus = JSONObject.parseObject(AESUtil.decrypt(response.getData()));
        return enStationStatus.getJSONArray("StationStatusInfos").toJavaList(EnStationStatusInfo.class);
    }


    /**
     * 充电桩统计
     *
     * @param stationId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public EnStationStatsInfo stationStats(String stationId, String startTime, String endTime) {
        var param = """
                {
                    "StationID":"%s",
                    "StartTime":"%s",
                    "EndTime":"%s"
                }
                """.formatted(stationId, startTime, endTime);
        var response = enPlusService.enPlusPost(EnPlusApi.EN_PLUS_QUERY_STATION_STATS.getApi(), enPlusService.buildParams(param));
        // TODO: 2023-08-12 包装成自己的数据格式
        var enStationStats = JSONObject.parseObject(AESUtil.decrypt(response.getData()));
        return enStationStats.getJSONObject("StationStats").toJavaObject(EnStationStatsInfo.class);
    }


    /**
     * 拉取EN+充电站信息数据并更新本地服务器数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pullEnStationInfos() {
        var stationVoList = queryStationInfo(1, 1000);
        var stationList = new ArrayList<Station>();
        var equipmentList = new ArrayList<EquipmentInfo>();
        stationVoList.forEach(vo -> {
            if (vo.getEquipmentInfos().size() > 0) {
                vo.getEquipmentInfos().forEach(item -> {
                    var equipment = new EquipmentInfo()
                            .setStationId(vo.getStationId())
                            .setShortId(item.getShortId())
                            .setPower(item.getConnectorInfos().get(0).getPower());
                    BeanUtils.copyProperties(item, equipment);
                    equipmentList.add(equipment);
                });
                equipmentList.sort(Comparator.comparing(EquipmentInfo::getShortId));
            }
            var station = new Station();
            BeanUtils.copyProperties(vo, station);
            stationList.add(station);
        });
        // 查询已存在的站点，只更新新增的站点和设备
        var stations = list().stream().map(Station::getStationId).toList();
        var equipments = equipmentInfoService.list().stream().map(EquipmentInfo::getEquipmentId).toList();
        saveBatch(stationList.stream().filter(station -> !stations.contains(station.getStationId())).toList());
        equipmentInfoService.saveBatch(equipmentList.stream().filter(equipmentInfo -> !equipments.contains(equipmentInfo.getEquipmentId())).toList());
    }

}
