package com.mortals.xhx.module.sitestat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.model.Result;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.xhx.common.code.DeviceStatusEnum;
import com.mortals.xhx.common.code.PlatformTypeEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.key.ErrorCode;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.common.utils.MemoryPagination;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.model.DeviceQuery;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.site.model.SiteQuery;
import com.mortals.xhx.module.site.model.SiteTreeSelect;
import com.mortals.xhx.module.site.service.SiteService;
import com.mortals.xhx.module.sitestat.dao.SitestatDao;
import com.mortals.xhx.module.sitestat.model.SitestatEntity;
import com.mortals.xhx.module.sitestat.model.SitestatQuery;
import com.mortals.xhx.module.sitestat.service.SitestatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

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

import static com.mortals.framework.web.BaseController.*;
import static com.mortals.xhx.common.key.ErrorCode.ERROR_TOKEN_EXPIRED_CONTENT;

/**
 * SitestatService
 * 站点统计 service实现
 *
 * @author zxfei
 * @date 2022-06-27
 */
@Service("sitestatService")
@Slf4j
public class SitestatServiceImpl extends AbstractCRUDCacheServiceImpl<SitestatDao, SitestatEntity, Long> implements SitestatService {

    @Autowired
    private ISiteFeign siteFeign;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private SiteService siteService;
    @Value("${platform.type:cloud}")
    private String platFormType;//版本，默认云服务版本


    @Override
    protected String getExtKey(SitestatEntity data) {
        return data.getSiteCode();
    }

    /**
     * 重写带分页的方法
     *
     * @param entity
     * @param pageInfo
     * @param context
     * @return
     * @throws AppException
     */
    @Override
    public Result<SitestatEntity> find(SitestatEntity entity, PageInfo pageInfo, Context context) throws AppException {
        Result<SitestatEntity> res = new Result<>();
        //根据站点查询所以站点子集列表
        Result<SitestatEntity> sitestatsAreaResult = getSitestatEntityResultByArea(entity, pageInfo, context, res);
        if (sitestatsAreaResult != null) return sitestatsAreaResult;

        Result<SitestatEntity> sitestatsResult = getSitestatsResult(entity, pageInfo, res);
        if (sitestatsResult != null) return sitestatsResult;

        Result<SitestatEntity> sitestatResult = getSitestatEntityResult(entity, pageInfo, context, res);
        if (sitestatResult != null) return sitestatResult;
        return new Result<>();
    }

    private Result<SitestatEntity> getSitestatEntityResult(SitestatEntity entity, PageInfo pageInfo, Context context, Result<SitestatEntity> res) {
        if (ObjectUtils.isEmpty(entity.getSiteId())) return null;
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.STANDALONE.getValue())) {
            //根据返回的id 筛选列表
            Map<Long, SitestatEntity> collectMap = this.find(new SitestatEntity(), context).stream().collect(Collectors.toMap(x -> x.getSiteId(), y -> y, (o, n) -> n));
            List<SitestatEntity> list = this.siteService.find(new SiteQuery().id(entity.getSiteId())).stream().filter(f -> collectMap.containsKey(f.getId())).map(m -> collectMap.get(m.getId())).collect(Collectors.toList());
            if (!ObjectUtils.isEmpty(entity.getSiteName())) {
                list = MemoryPagination.search(entity.getSiteName(), list);
            }
            pageInfo.setTotalResult(list.size());
            List<SitestatEntity> siteStatList = MemoryPagination.pagination(list, pageInfo.getCurrPage(), pageInfo.getPrePageResult());
            res.setList(siteStatList);
            res.setPageInfo(pageInfo);
        } else {
            SitePdu sitePdu = new SitePdu();
            sitePdu.setId(entity.getSiteId());
            Rest<List<SitePdu>> result = siteFeign.getFlatSitesBySiteId(sitePdu);
            // log.info("siteList:{}",JSON.toJSONString(result));
            if (result.getCode() == YesNoEnum.YES.getValue()) {
                //根据返回的id 筛选列表
                Map<Long, SitestatEntity> collectMap = this.find(new SitestatEntity(), context).stream().collect(Collectors.toMap(x -> x.getSiteId(), y -> y, (o, n) -> n));
                List<SitestatEntity> list = result.getData().stream().filter(f -> collectMap.containsKey(f.getId())).map(m -> collectMap.get(m.getId())).collect(Collectors.toList());
                if (!ObjectUtils.isEmpty(entity.getSiteName())) {
                    list = MemoryPagination.search(entity.getSiteName(), list);
                }
                // log.info("siteStatList:{}",JSON.toJSONString(list));
                pageInfo.setTotalResult(list.size());
                List<SitestatEntity> siteStatList = MemoryPagination.pagination(list, pageInfo.getCurrPage(), pageInfo.getPrePageResult());
                res.setList(siteStatList);
                res.setPageInfo(pageInfo);
            } else {
                log.info("error resp:{}", JSON.toJSONString(result));
            }
        }

        return res;
    }

    private Result<SitestatEntity> getSitestatsResult(SitestatEntity entity, PageInfo pageInfo, Result<SitestatEntity> res) {
        List<SitestatEntity> collect = null;
        if (ObjectUtils.isEmpty(entity.getSiteIdList())) return null;
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.CLOUD.getValue())) {
            collect = entity.getSiteIdList().stream().flatMap(siteId -> {
                SitePdu sitePdu = new SitePdu();
                sitePdu.setId(siteId);
                Rest<List<SitePdu>> result = siteFeign.getFlatSitesBySiteId(sitePdu);
                if (result.getCode() == YesNoEnum.YES.getValue()) {
                    //根据返回的id 筛选列表
                    Map<Long, SitestatEntity> collectMap = this.find(new SitestatEntity()).stream().collect(Collectors.toMap(x -> x.getSiteId(), y -> y, (o, n) -> n));
                    List<SitestatEntity> list = result.getData().stream()
                            .filter(f -> collectMap.containsKey(f.getId()))
                            .map(m -> {
                                SitestatEntity sitestatEntity = collectMap.get(m.getId());
                                sitestatEntity.setLng(m.getLongitude());
                                sitestatEntity.setLat(m.getLatitude());
                                sitestatEntity.setAddress(m.getDetailAddress());
                                sitestatEntity.setLeadingOfficial(m.getLeadingOfficial());
                                sitestatEntity.setLeadingOfficialTelephone(m.getLeadingOfficialTelephone());
                                return sitestatEntity;
                            }).collect(Collectors.toList());
                    if (!ObjectUtils.isEmpty(list)) {
                        return list.stream();
                    }

                }
                return new ArrayList<SitestatEntity>().stream();
            }).distinct().collect(Collectors.toList());

        } else {
            collect = entity.getSiteIdList().stream().flatMap(siteId -> {
                //根据返回的id 筛选列表
                Map<Long, SitestatEntity> collectMap = this.find(new SitestatEntity()).stream().collect(Collectors.toMap(x -> x.getSiteId(), y -> y, (o, n) -> n));
                List<SitestatEntity> list = siteService.find(new SiteQuery().id(siteId)).stream()
                        .filter(f -> collectMap.containsKey(f.getId()))
                        .map(m -> {
                            SitestatEntity sitestatEntity = collectMap.get(m.getId());
                            sitestatEntity.setLng(m.getLongitude());
                            sitestatEntity.setLat(m.getLatitude());
                            sitestatEntity.setAddress(m.getDetailAddress());
                            sitestatEntity.setLeadingOfficial(m.getLeadingOfficial());
                            sitestatEntity.setLeadingOfficialTelephone(m.getLeadingOfficialTelephone());
                            return sitestatEntity;
                        }).collect(Collectors.toList());
                if (!ObjectUtils.isEmpty(list)) {
                    return list.stream();
                }
                return new ArrayList<SitestatEntity>().stream();
            }).distinct().collect(Collectors.toList());
        }
        if (!ObjectUtils.isEmpty(entity.getSiteName())) {
            collect = MemoryPagination.search(entity.getSiteName(), collect);
        }
        pageInfo.setTotalResult(collect.size());
        List<SitestatEntity> siteStatList = MemoryPagination.pagination(collect, pageInfo.getCurrPage(), pageInfo.getPrePageResult());
        res.setList(siteStatList);
        res.setPageInfo(pageInfo);
        return res;
    }


    private Result<SitestatEntity> getSitestatEntityResultByArea(SitestatEntity entity, PageInfo pageInfo, Context context, Result<SitestatEntity> res) {
        if (ObjectUtils.isEmpty(entity.getAreaCode())) return null;
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.STANDALONE.getValue())) {
            //根据返回的id 筛选列表 todo
            Map<Long, SitestatEntity> collectMap = this.find(new SitestatEntity(), context).stream().collect(Collectors.toMap(x -> x.getSiteId(), y -> y, (o, n) -> n));
            List<SitestatEntity> list = this.siteService.find(new SiteQuery().id(entity.getSiteId())).stream().filter(f -> collectMap.containsKey(f.getId())).map(m -> collectMap.get(m.getId())).collect(Collectors.toList());
            if (!ObjectUtils.isEmpty(entity.getSiteName())) {
                list = MemoryPagination.search(entity.getSiteName(), list);
            }
            pageInfo.setTotalResult(list.size());
            List<SitestatEntity> siteStatList = MemoryPagination.pagination(list, pageInfo.getCurrPage(), pageInfo.getPrePageResult());
            res.setList(siteStatList);
            res.setPageInfo(pageInfo);
        } else {
            SitePdu sitePdu = new SitePdu();
            List<String> areaCodeList = new ArrayList<>();
            sitePdu.setAreaCode(entity.getAreaCode());
            Rest<List<SitePdu>> result = siteFeign.getFlatSitesByAreaCode(sitePdu);
            log.info("areaSiteList:{}", JSON.toJSONString(result));
            if (result.getCode() == YesNoEnum.YES.getValue()) {
                //根据返回的id 筛选列表
                Map<Long, SitestatEntity> collectMap = this.find(new SitestatEntity(), context).stream().collect(Collectors.toMap(x -> x.getSiteId(), y -> y, (o, n) -> n));
                List<SitestatEntity> list = result.getData().stream().filter(f -> collectMap.containsKey(f.getId())).map(m -> collectMap.get(m.getId())).collect(Collectors.toList());
                if (!ObjectUtils.isEmpty(entity.getSiteName())) {
                    list = MemoryPagination.search(entity.getSiteName(), list);
                }
                //  log.info("siteStatList:{}",JSON.toJSONString(list));
                pageInfo.setTotalResult(list.size());
                List<SitestatEntity> siteStatList = MemoryPagination.pagination(list, pageInfo.getCurrPage(), pageInfo.getPrePageResult());
                res.setList(siteStatList);
                res.setPageInfo(pageInfo);
            } else {
                log.info("error resp:{}", JSON.toJSONString(result));
            }
        }

        return res;
    }

    @Override
    public String getSiteTree(Context context) {
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.CLOUD.getValue())) {
            String token = context.getUser().getToken();
            JSONObject jsonObject = new JSONObject();
            Map<String, Object> model = new HashMap<>();
            if (!ObjectUtils.isEmpty(token)) {
                String resp = siteFeign.siteTree(token);
                Rest<String> rest = JSON.parseObject(resp, new TypeReference<Rest<String>>() {
                });
                if (rest.getCode() == YesNoEnum.YES.getValue()) {
                    String siteTreeSelectStr = rest.getData();
                    JSONObject json = JSON.parseObject(siteTreeSelectStr);
                    JSONArray jsonArray = json.getJSONArray("siteTree");

                    if (ObjectUtils.isEmpty(jsonArray)) {
                        jsonObject.put(KEY_RESULT_DATA, new JSONArray());
                        jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
                        return jsonObject.toJSONString();
                    }
                    List<SiteTreeSelect> collect = jsonArray.stream().map(item -> {
                        SiteTreeSelect siteTreeSelect = JSON.parseObject(item.toString(), SiteTreeSelect.class);
                        return siteTreeSelect;
                    }).collect(Collectors.toList());
                    model.put(KEY_RESULT_DATA, collect);
                    jsonObject.put(KEY_RESULT_DATA, model);
                    jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
                    return jsonObject.toJSONString();

                }
                jsonObject.put(KEY_RESULT_DATA, model);
                jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
                return jsonObject.toJSONString();
            }
        } else {
            JSONObject jsonObject = new JSONObject();
            Map<String, Object> model = new HashMap<>();
            List<SiteTreeSelect> siteTree = siteService.getSiteTree(context);
            if (ObjectUtils.isEmpty(siteTree)) {
                log.info("为初始化站点树，重新构建！");
                siteTree = siteService.siteTree(context);
            }
            model.put("siteTree", siteTree);
            jsonObject.put(KEY_RESULT_DATA, model);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
            return jsonObject.toJSONString();
        }
        return JSON.toJSONString(Rest.fail(ErrorCode.ERROR_TOKEN_EXPIRED, ERROR_TOKEN_EXPIRED_CONTENT));
    }

    @Override
    public void updateSiteStat(SitestatEntity entity, Context context) {
        //更新统计信息，触发
        List<DeviceEntity> deviceList = deviceService.find(new DeviceQuery().siteId(entity.getSiteId()));
        //分别统计数据
        entity.setDeviceTotal(deviceList.size());

        Long onlineCount = deviceList.stream().filter(f -> f.getDeviceStatus() == DeviceStatusEnum.在线.getValue()).count();
        Long offlineCount = deviceList.stream().filter(f -> f.getDeviceStatus() == DeviceStatusEnum.离线.getValue()).count();
        Long unActiveCount = deviceList.stream().filter(f -> f.getDeviceStatus() == DeviceStatusEnum.未激活.getValue()).count();
        Long stopCount = deviceList.stream().filter(f -> f.getEnabled() == YesNoEnum.NO.getValue()).count();

        entity.setOnlineCount(onlineCount.intValue());
        entity.setOfflineCount(offlineCount.intValue());
        entity.setStopCount(stopCount.intValue());
        entity.setUnActiveCount(unActiveCount.intValue());

        //查询站点统计记录是否存在，如果存在则修改，否则新增
        SitestatEntity sitestatEntity = this.selectOne(new SitestatQuery().siteId(entity.getSiteId()));
        if (ObjectUtils.isEmpty(sitestatEntity)) {
            //新增
            entity.setCreateUserId(getContextUserId(context));
            entity.setCreateTime(new Date());
            this.save(entity, context);
        } else {
            //修改
            entity.setId(sitestatEntity.getId());
            entity.setUpdateUserId(getContextUserId(context));
            entity.setUpdateTime(new Date());
            this.update(entity, context);
        }

    }


    public static void main(String[] args) {

        String siteTreeSelectStr = "[{\"areaCode\":\"511500000000\",\"children\":[{\"areaCode\":\"511502000000\",\"children\":[{\"areaCode\":\"511502012000\",\"children\":[{\"areaCode\":\"511502012001\",\"icon\":\"el-icon-wind-power\",\"id\":\"4\",\"isLeaf\":true,\"label\":\"东街站点\",\"latitude\":\"2\",\"longitude\":\"1\",\"siteCode\":\"511502012001-0001\",\"type\":\"site\"}],\"icon\":\"el-icon-place\",\"id\":\"1b01f5486d63467aaa24eafbee797b47\",\"isLeaf\":false,\"label\":\"合江门街道\",\"type\":\"area\"}],\"icon\":\"el-icon-wind-power\",\"id\":\"2\",\"isLeaf\":false,\"label\":\"翠屏区市民中心\",\"latitude\":\"31.467450\",\"longitude\":\"104.679114\",\"siteCode\":\"511502000000-0001\",\"type\":\"site\"},{\"areaCode\":\"511521000000\",\"children\":[],\"icon\":\"el-icon-wind-power\",\"id\":\"3\",\"isLeaf\":false,\"label\":\"徐州区办事处\",\"latitude\":\"28.758065\",\"longitude\":\"104.647877\",\"siteCode\":\"511521000000-0001\",\"type\":\"site\"}],\"icon\":\"el-icon-wind-power\",\"id\":\"1\",\"isLeaf\":false,\"label\":\"四川恒升信达科技有限公司\",\"latitude\":\"30.595081\",\"longitude\":\"104.062983\",\"siteCode\":\"511500000000-0001\",\"type\":\"site\"}]";

        JSONArray jsonArray = JSON.parseArray(siteTreeSelectStr);

        List<SiteTreeSelect> collect = jsonArray.stream().map(item -> {
            SiteTreeSelect siteTreeSelect = JSON.parseObject(item.toString(), SiteTreeSelect.class);
            return siteTreeSelect;
        }).collect(Collectors.toList());

        System.out.println(JSON.toJSONString(collect));

    }

}