package com.usky.fire.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.core.util.Arith;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.fire.domain.DemMicroStation;
import com.usky.fire.domain.DemWaterSource;
import com.usky.fire.mapper.DemMicroStationMapper;
import com.usky.fire.mapper.DemWaterSourceMapper;
import com.usky.fire.service.DemWaterSourceMaintainService;
import com.usky.fire.service.DemWaterSourceService;
import com.usky.fire.service.po.FireWaterPO;
import com.usky.fire.service.util.OnlineMethod;
import com.usky.fire.service.vo.FireWaterStatisticsVO;
import com.usky.fire.service.vo.DemWaterSourceExportVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 水源信息表 服务实现类
 * </p>
 *
 * @author JCB
 * @since 2022-10-24
 */
@Service
public class DemWaterSourceServiceImpl extends AbstractCrudService<DemWaterSourceMapper, DemWaterSource> implements DemWaterSourceService {

    @Autowired
    private DemWaterSourceMaintainService demWaterSourceMaintainService;

    @Autowired
    private DemMicroStationMapper demMicroStationMapper;

    @Override
    public CommonPage<Map<String, Object>> waterSourceList(String waterName, Integer id, Integer pageNum, Integer pageSize) {
        List<Map<String, Object>> list = new ArrayList<>();
        IPage<DemWaterSource> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<DemWaterSource> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DemWaterSource::getId, DemWaterSource::getWaterName, DemWaterSource::getWaterAddress,
                DemWaterSource::getWaterType, DemWaterSource::getOrganizateName, DemWaterSource::getWaterForm,
                DemWaterSource::getAvailableStatusName, DemWaterSource::getAvailableStatus, DemWaterSource::getWaterNature,
                DemWaterSource::getBuildTime, DemWaterSource::getPipeCompany, DemWaterSource::getContactMode,
                DemWaterSource::getFireAbbreviat, DemWaterSource::getPipePressure, DemWaterSource::getHydrantInterface)
                .eq(DemWaterSource::getDeleteFlag, 0)
                .like(StringUtils.isNotBlank(waterName), DemWaterSource::getWaterName, waterName)
                .orderByDesc(DemWaterSource::getId);
        page = this.page(page, queryWrapper);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            for (int i = 0; i < page.getRecords().size(); i++) {
                Map<String, Object> map = new HashMap<>();
                map.put("id", page.getRecords().get(i).getId());
                map.put("waterName", page.getRecords().get(i).getWaterName());
                map.put("waterAddress", page.getRecords().get(i).getWaterAddress());
                map.put("waterType", page.getRecords().get(i).getWaterType());
                map.put("organizateName", page.getRecords().get(i).getOrganizateName());
                map.put("waterForm", page.getRecords().get(i).getWaterForm());
                map.put("availableStatusName", page.getRecords().get(i).getAvailableStatusName());
                map.put("availableStatus", page.getRecords().get(i).getAvailableStatus());
                map.put("waterNature", page.getRecords().get(i).getWaterNature());
                map.put("buildTime", page.getRecords().get(i).getBuildTime());
                map.put("pipeCompany", page.getRecords().get(i).getPipeCompany());
                map.put("contactMode", page.getRecords().get(i).getContactMode());
                map.put("fireAbbreviat", page.getRecords().get(i).getFireAbbreviat());
                map.put("pipePressure", page.getRecords().get(i).getPipePressure());
                map.put("hydrantInterface", page.getRecords().get(i).getHydrantInterface());
                list.add(map);
            }
        }
        return new CommonPage<>(list, page.getTotal(), pageSize, pageNum);
    }

    @Override
    public List<DemWaterSourceExportVO> waterSourceListExport(String waterName){
        List<DemWaterSourceExportVO> list = new ArrayList<>();
        LambdaQueryWrapper<DemWaterSource> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DemWaterSource::getId, DemWaterSource::getWaterName, DemWaterSource::getWaterAddress,
                DemWaterSource::getWaterType, DemWaterSource::getOrganizateName, DemWaterSource::getWaterForm,
                DemWaterSource::getAvailableStatusName, DemWaterSource::getAvailableStatus, DemWaterSource::getWaterNature,
                DemWaterSource::getBuildTime, DemWaterSource::getPipeCompany, DemWaterSource::getContactMode,
                DemWaterSource::getFireAbbreviat, DemWaterSource::getPipePressure, DemWaterSource::getHydrantInterface)
                .eq(DemWaterSource::getDeleteFlag, 0)
                .like(StringUtils.isNotBlank(waterName), DemWaterSource::getWaterName, waterName)
                .orderByDesc(DemWaterSource::getId);
        List<DemWaterSource> list1 = this.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(list1)) {
            for (int i = 0; i < list1.size(); i++) {
                DemWaterSourceExportVO demWaterSourceExportVO = new DemWaterSourceExportVO();
                demWaterSourceExportVO.setWaterName(list1.get(i).getWaterName());
                demWaterSourceExportVO.setWaterAddress(list1.get(i).getWaterAddress());
                demWaterSourceExportVO.setWaterType(list1.get(i).getWaterType());
                demWaterSourceExportVO.setOrganizateName(list1.get(i).getOrganizateName());
                demWaterSourceExportVO.setWaterForm(list1.get(i).getWaterForm());
                demWaterSourceExportVO.setAvailableStatusName(list1.get(i).getAvailableStatusName());
                demWaterSourceExportVO.setWaterNature(list1.get(i).getWaterNature());
                demWaterSourceExportVO.setBuildTime((list1.get(i).getBuildTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                demWaterSourceExportVO.setPipeCompany(list1.get(i).getPipeCompany());
                demWaterSourceExportVO.setContactMode(list1.get(i).getContactMode());
                demWaterSourceExportVO.setFireAbbreviat(list1.get(i).getFireAbbreviat());
                demWaterSourceExportVO.setPipePressure(list1.get(i).getPipePressure());
                demWaterSourceExportVO.setHydrantInterface(list1.get(i).getHydrantInterface());
                list.add(demWaterSourceExportVO);
            }
        }

        return list;
    }

    @Override
    public void updateWaterSource(DemWaterSource demWaterSource) {
        this.updateById(demWaterSource);
    }

    @Override
    public void delWaterSource(Integer id) {
        DemWaterSource demWaterSource = new DemWaterSource();
        demWaterSource.setId(id);
        demWaterSource.setDeleteFlag("1");
        this.updateById(demWaterSource);
    }

    @Override
    public List<Object> waterSourceList(String streetTown) {
        IPage<DemWaterSource> page = new Page<>(1, 500);
        LambdaQueryWrapper<DemWaterSource> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DemWaterSource::getId, DemWaterSource::getWaterName, DemWaterSource::getWaterAddress,
                DemWaterSource::getGisX, DemWaterSource::getGisY)
                .eq(DemWaterSource::getDeleteFlag, 0)
                .orderByDesc(DemWaterSource::getId);
        page = this.page(page, queryWrapper);
        List<DemWaterSource> list1 = page.getRecords();
        List<Object> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list1)) {
            for (int i = 0; i < list1.size(); i++) {
                Map<String, Object> map = new HashMap<>();
                map.put("id", list1.get(i).getId());
                map.put("waterName", list1.get(i).getWaterName());
                map.put("waterAddress", list1.get(i).getWaterAddress());
                map.put("longitude", list1.get(i).getGisX());
                map.put("latitude", list1.get(i).getGisY());
                list.add(map);
            }
        }
        return list;
    }

    @Override
    public List<DemWaterSource> waterSourceList() {
        LambdaQueryWrapper<DemWaterSource> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DemWaterSource::getId, DemWaterSource::getWaterType, DemWaterSource::getWaterName,
                DemWaterSource::getWaterAddress, DemWaterSource::getWaterCompany, DemWaterSource::getContactMode,
                DemWaterSource::getGisX, DemWaterSource::getGisY)
                .eq(DemWaterSource::getDeleteFlag, 0)
                .orderByDesc(DemWaterSource::getId);
        List<DemWaterSource> list = this.list(queryWrapper);
        return list;
    }

    @Override
    public List<Map<String, Object>> surroundingResources(double longitude, double latitude, Integer distance) {
        List<Map<String, Object>> list = new ArrayList<>();
        List<DemWaterSource> list1 = this.waterSourceList();
        List<DemMicroStation> list2 = this.microStationScatterer();
        if (CollectionUtils.isNotEmpty(list1)) {
            for (int i = 0; i < list1.size(); i++) {
                Map<String, Object> map = new HashMap<>();
                int distance1 = 0;
                if (StringUtils.isNotBlank(list1.get(i).getGisX()) && StringUtils.isNotBlank(list1.get(i).getGisY())) {
                    double gisX = Double.valueOf(list1.get(i).getGisX());
                    double gisY = Double.valueOf(list1.get(i).getGisY());
                    double v = OnlineMethod.GetDistance(longitude, latitude, gisX, gisY);
                    distance1 = new Double(v).intValue();
                    map.put("distance", v);
                } else {
                    map.put("distance", null);
                }
                map.put("id", list1.get(i).getId());
                map.put("waterType", list1.get(i).getWaterType());
                map.put("waterName", list1.get(i).getWaterName());
                map.put("waterAddress", list1.get(i).getWaterAddress());
                map.put("waterCompany", list1.get(i).getWaterCompany());
                map.put("contactMode", list1.get(i).getContactMode());
                map.put("longitude", list1.get(i).getGisX());
                map.put("latitude", list1.get(i).getGisY());
                map.put("chargeName", null);
                if (distance1 <= distance && distance1 != 0) {
                    list.add(map);
                }
            }
        }

        if (CollectionUtils.isNotEmpty(list2)) {
            for (int i = 0; i < list2.size(); i++) {
                Map<String, Object> map = new HashMap<>();
                int distance1 = 0;
                if (StringUtils.isNotBlank(list2.get(i).getLongitude().toString()) && StringUtils.isNotBlank(list2.get(i).getDimension().toString())) {
                    double gisX = Double.valueOf(list2.get(i).getLongitude().toString());
                    double gisY = Double.valueOf(list2.get(i).getDimension().toString());
                    double v = OnlineMethod.GetDistance(longitude, latitude, gisX, gisY);
                    distance1 = new Double(v).intValue();
                    map.put("distance", v);
                } else {
                    map.put("distance", null);
                }
                map.put("id", list2.get(i).getId());
                map.put("waterType", "消防站");
                map.put("waterName", list2.get(i).getStationName());
                map.put("waterAddress", list2.get(i).getAddress());
                map.put("waterCompany", null);
                map.put("chargeName", list2.get(i).getChargeName());
                map.put("contactMode", list2.get(i).getChargePhone());
                map.put("longitude", list2.get(i).getLongitude());
                map.put("latitude", list2.get(i).getDimension());
                if (distance1 <= distance && distance1 != 0) {
                    list.add(map);
                }
            }
        }
        return list;
    }


    @Override
    public List<Object> waterSourceScatterer(String scattererType, String streetTown) {
        List<Object> list = new ArrayList<>();
        switch (scattererType) {
            case "消火栓":
                list = this.waterSourceList(streetTown);
                break;
            case "天然水源":
                list = demWaterSourceMaintainService.waterSourceMaintainScatterer(streetTown);
                break;
            default:
                throw new BusinessException("该类型点位未定义");
        }
        return list;
    }

    @Override
    public List<DemMicroStation> microStationScatterer() {
        LambdaQueryWrapper<DemMicroStation> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(DemMicroStation::getId, DemMicroStation::getStationName, DemMicroStation::getLongitude,
                DemMicroStation::getDimension, DemMicroStation::getAddress, DemMicroStation::getChargeName,
                DemMicroStation::getChargePhone)
                .eq(DemMicroStation::getDeleteFlag, "0")
                .orderByDesc(DemMicroStation::getId);
        List<DemMicroStation> list = demMicroStationMapper.selectList(queryWrapper);
        return list;
    }

    @Override
    public int waterSourceCount(String waterType, String waterNature, String waterForm, String startTime, String endTime, String availableStatus) {
        LambdaQueryWrapper<DemWaterSource> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(DemWaterSource::getDeleteFlag, 0)
                .eq(StringUtils.isNotBlank(waterType), DemWaterSource::getWaterType, waterType)
                .eq(StringUtils.isNotBlank(waterNature), DemWaterSource::getWaterNature, waterNature)
                .eq(StringUtils.isNotBlank(waterForm), DemWaterSource::getWaterForm, waterForm)
                .eq(StringUtils.isNotBlank(availableStatus), DemWaterSource::getAvailableStatus, availableStatus)
                .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), DemWaterSource::getBdpAudit, startTime, endTime);
        int count = this.count(queryWrapper);
        return count;
    }

    @Override
    public FireWaterStatisticsVO getFireWaterStatistics(String startTime, String endTime) {
        FireWaterStatisticsVO fireWaterStatisticsVO = new FireWaterStatisticsVO();
        fireWaterStatisticsVO.setMunicipalFireCode(
                this.waterSourceCount("消火栓", "市政", null, startTime, endTime, null));
        fireWaterStatisticsVO.setCommunityFireCode(
                this.waterSourceCount("消火栓", "居民", null, startTime, endTime, null));
        fireWaterStatisticsVO.setUnitFireCode(
                this.waterSourceCount("消火栓", "单位", null, startTime, endTime, null));
        fireWaterStatisticsVO.setNaturalWater(
                this.waterSourceCount("天然水源", null, null, startTime, endTime, null));
        fireWaterStatisticsVO.setMunicipalWater(
                this.waterSourceCount(null, "市政", null, startTime, endTime, null));
        fireWaterStatisticsVO.setResidentWater(
                this.waterSourceCount(null, "居民", null, startTime, endTime, null));
        fireWaterStatisticsVO.setUnitWater(
                this.waterSourceCount(null, "单位", null, startTime, endTime, null));
        fireWaterStatisticsVO.setMunicipalGetWater(
                this.waterSourceCount(null, null, "市政", startTime, endTime, null));
        fireWaterStatisticsVO.setLandGetWater(
                this.waterSourceCount(null, null, "地上", startTime, endTime, null));
        Integer total = this.waterSourceCount(null, null, null, startTime, endTime, null);
        fireWaterStatisticsVO.setMunicipalGetWaterRadio(Arith.div(fireWaterStatisticsVO.getMunicipalGetWater(), total));
        fireWaterStatisticsVO.setLandGetWaterRadio(Arith.div(fireWaterStatisticsVO.getLandGetWater(), total));
        Integer waterIntact = this.waterSourceCount(null, null, null, startTime, endTime, "1");
        fireWaterStatisticsVO.setWaterIntact(Arith.div(waterIntact, total));
        return fireWaterStatisticsVO;
    }

    @Override
    public CommonPage<FireWaterPO> page(Integer current, Integer size, String startTime, String endTime) {
        List<FireWaterPO> list = new ArrayList<>();
        Page<DemWaterSource> page = new Page<>(current, size);
        LambdaQueryWrapper<DemWaterSource> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), DemWaterSource::getBdpAudit, startTime, endTime);
        page = this.page(page, queryWrapper);
        page.getRecords().forEach(stringObjectMap -> list.add(enhanceFireWaterPo(stringObjectMap)));
        return new CommonPage<>(list, page.getTotal(), page.getSize(), page.getCurrent());
    }

    /**
     * map转换为unitpo
     *
     * @param fireWaterMap
     * @return
     */
    public FireWaterPO enhanceFireWaterPo(DemWaterSource fireWaterMap) {
        FireWaterPO fireWaterPo = new FireWaterPO();
        fireWaterPo.setAddress(fireWaterMap.getWaterAddress());
        fireWaterPo.setPhone(Optional.ofNullable(fireWaterMap.getContactMode()).orElse(""));
        fireWaterPo.setType(fireWaterMap.getWaterType());
        fireWaterPo.setJurisdictionalAgency(fireWaterMap.getOrganizateName());
        fireWaterPo.setDetachmentName(fireWaterMap.getBranchName());
        fireWaterPo.setGetWaterType(fireWaterMap.getWaterForm());
        fireWaterPo.setWaterAdministrative(Optional.ofNullable(fireWaterMap.getWaterNature()).orElse(""));
        fireWaterPo.setStatus(fireWaterMap.getAvailableStatus() + "");
        fireWaterPo.setWaterUnit(fireWaterMap.getWaterCompany());
        fireWaterPo.setWaterGage(fireWaterMap.getPipePressure());
        fireWaterPo.setGisX(fireWaterMap.getGisX());
        fireWaterPo.setGisY(fireWaterMap.getGisY());
        fireWaterPo.setGisBaiDuX(fireWaterMap.getGisXBaidu());
        fireWaterPo.setGisBaiDuY(fireWaterMap.getGisYBaidu());
        return fireWaterPo;
    }

}
