package com.fastbee.ggroup.service.impl;


import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fastbee.common.exception.ServiceException;
import com.fastbee.common.utils.json.JsonStrUtil;
import com.fastbee.common.utils.validate.LongitudeLatitudeValidateUtils;
import com.fastbee.ggroup.domain.GSiteGroups;
import com.fastbee.ggroup.domain.dto.GGroupSiteDto;
import com.fastbee.ggroup.domain.dto.GGroupSiteRelateDto;
import com.fastbee.ggroup.domain.dto.GSitesEditDto;
import com.fastbee.ggroup.domain.dto.GSitesSelectDto;
import com.fastbee.ggroup.mapper.GSiteGroupsMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.fastbee.ggroup.mapper.GSitesMapper;
import com.fastbee.ggroup.domain.GSites;
import com.fastbee.ggroup.service.IGSitesService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 站点Service业务层处理
 * 
 * @author kerwincui
 * &#064;date  2024-09-29
 */
@Service
@Slf4j
public class GSitesServiceImpl extends ServiceImpl<GSiteGroupsMapper,GSiteGroups> implements IGSitesService {

    private final GSitesMapper gSitesMapper;
    private final GSiteGroupsMapper gSiteGroupsMapper;

    public GSitesServiceImpl(GSitesMapper gSitesMapper, GSiteGroupsMapper gSiteGroupsMapper) {
        this.gSitesMapper = gSitesMapper;
        this.gSiteGroupsMapper = gSiteGroupsMapper;
    }

    /**
     * 查询站点
     */
    @Override
    public GSites selectGSitesById(Long id) {
        return gSitesMapper.selectGSitesById(id);
    }

    /**
     * 查询全部站点列表
     */
    @Override
    public List<GSites> selectGSitesList(GSitesSelectDto gSites) {
        return new LambdaQueryChainWrapper<>(gSitesMapper)
                .select(GSites::getId, GSites::getName, GSites::getIcon, GSites::getType,GSites::getAreaCode,GSites::getFullAreaCode)
                .eq(GSites::getProjectId, gSites.getProjectId())
                .list();
    }

    /**
     * 新增站点
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertGSites(GGroupSiteDto gGroupSiteDto) {

        GSites gSites = new GSites();
        BeanUtils.copyProperties(gGroupSiteDto, gSites);
        //是否存在同名站点
        GSites sameNameSite = gSitesMapper.selectOne(new LambdaQueryWrapper<GSites>()
                .select(GSites::getName, GSites::getId)
                .eq(GSites::getName, gGroupSiteDto.getName().trim()));
        if (Objects.nonNull(sameNameSite)) {
            throw new ServiceException("站点名称重复！");
        }
        //是否选择行政区域
        if (StringUtils.isBlank(gGroupSiteDto.getAreaCode())) {
            throw new ServiceException("请选择行政区域！");
        }
        //行政区完整编码校验
        if(StringUtils.isBlank(gGroupSiteDto.getFullAreaCode())){
            throw new ServiceException("请提交行政区域完整编码！");
        }
        //站点图标校验
        if(StringUtils.isBlank(gGroupSiteDto.getIcon())){
            throw new ServiceException("请选择站点图标！");
        }
        //读取上传的站点图json信息进行校验并赋值到对应属性
        getReadJsonFileContent(gSites);
        //设置行政区域编码
        gSites.setAreaCode(gGroupSiteDto.getAreaCode());
        //设置行政区域完整编码
        gSites.setFullAreaCode(gGroupSiteDto.getFullAreaCode());
        //插入站点表
        int inserted = gSitesMapper.insert(gSites);
        gGroupSiteDto.setSiteId(gSites.getId());
        //插入关系表
        int inserted1 = gSiteGroupsMapper.insertGSiteGroups(gGroupSiteDto);
        return inserted == 1 && inserted1 == 1 ? 1 : 0;
    }

    /**
     * 读取上传的站点图json信息进行校验并赋值到对应属性
     */
    private void getReadJsonFileContent(GSites gSites) {
        //TODO 路径优化
        //发起http请求获取json数据
        String space = gSites.getSpace();
        if(StringUtils.isBlank(space)){
            throw new ServiceException("请上传站点地图json数据！");
        }
        //判断space是否是完整url还是相对url
        if(!(space.contains("http://") || space.contains("https://"))){
            //如果是相对url则代表未修改
            return;
        }
        String jsonData = HttpUtil.get(space);
        System.err.println("获取到json:"+jsonData);

        //读取文件内容
        if (Objects.isNull(jsonData)) {
            throw new ServiceException("上传站点地图json数据为空！");
        }
        //校验文件内容是否是json格式
        if (!JsonStrUtil.isValidJson(jsonData)) {
            throw new ServiceException("json格式不正确！");
        }
        //校验json对象是否合法
        JSONObject jsonObject = JSONUtil.parseObj(jsonData);
        if (!jsonObject.containsKey("coordinates")) {
            throw new ServiceException("json缺少coordinates属性！");
        }
        //判断coordinates的值必须为点线面的一种
        Object coordinates = jsonObject.get("coordinates");
        //解析为数组
        if (!(coordinates instanceof JSONArray)) {
            throw new ServiceException("coordinates的值必须为数组类型！");
        }
        JSONArray jsonArray = JSONUtil.parseArray(coordinates);
        //判断数组每个元素必须为经度或纬度
        for (Object o : jsonArray) {
           if(!LongitudeLatitudeValidateUtils.isLongitudeOrLatitude(o.toString())){
                throw new ServiceException("coordinates数组元素必须为经度或纬度！");
            }
        }
        int startIndex = space.indexOf("/profile/upload/");
        String relativeUrl = space.substring(startIndex);
        gSites.setSpace(relativeUrl);
        gSites.setSpaceValue(jsonData);
    }


    /**
     * 修改站点
     */
    @Override
    public int updateGSites(GSitesEditDto gSitesEditDto) {
        //是否存在同名站点
        GSites sameNameSite = gSitesMapper.selectOne(new LambdaQueryWrapper<GSites>()
                .select(GSites::getName, GSites::getId)
                .eq(GSites::getName, gSitesEditDto.getName().trim())
                .ne(GSites::getId, gSitesEditDto.getId()));
        if (Objects.nonNull(sameNameSite)) {
            throw new ServiceException("站点名称重复！");
        }

        GSites sites = new GSites();
        BeanUtils.copyProperties(gSitesEditDto, sites);
        //读取上传的站点图json信息进行校验并赋值到对应属性
        getReadJsonFileContent(sites);
        return gSitesMapper.updateById(sites);
    }



    /**
     * 批量删除站点
     */
    @Override
    public int deleteGSitesByIds(Long[] ids) {
        return gSitesMapper.deleteGSitesByIds(ids);
    }

    /**
     * 删除站点信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteGSitesById(Long id) {
        //判断该站点是否跟其他组建立关系，没有跟其他组建立关系则删除关联，并删除该站点
        List<GSiteGroups> gSiteGroupsList = new LambdaQueryChainWrapper<>(gSiteGroupsMapper)
                .select(GSiteGroups::getParentId, GSiteGroups::getSiteId)
                .eq(GSiteGroups::getId, id)
                .list();
        List<GSiteGroups> gSiteGroupsList1 = new LambdaQueryChainWrapper<>(gSiteGroupsMapper)
                .select(GSiteGroups::getParentId, GSiteGroups::getSiteId)
                .eq(GSiteGroups::getSiteId, gSiteGroupsList.get(0).getSiteId())
                .ne(GSiteGroups::getParentId, gSiteGroupsList.get(0).getParentId())
                .list();
        //没有跟其他组建立关联
        if (gSiteGroupsList1.isEmpty()){
            //删除关联
            int deleteGSiteGroupsById = gSiteGroupsMapper.deleteById(id);
            //删除站点
            int deleteSitesById= gSitesMapper.deleteById(gSiteGroupsList.get(0).getSiteId());
            return deleteSitesById==1&& deleteGSiteGroupsById==1? 1 : 0;
        }
        //如果有跟其他组建立关系，只删除跟当前组的关系
        return gSiteGroupsMapper.deleteById(id);
    }

    /**
     * 站点关联组
     */
    @Override
    public int relateGroup(GGroupSiteRelateDto gGroupSiteRelateDto) {
        return super.saveBatch(gGroupSiteRelateDto.getSiteIds()
                .stream()
                //转成数据库存储对象
                .map(siteId -> {
                    GSiteGroups gSiteGroups = new GSiteGroups();
                    gSiteGroups.setSiteId(siteId);
                    return gSiteGroups;
                })
                .collect(Collectors.toList())
                .stream()
                //设置项目id,所属组id
                .peek(item -> {
                    item.setParentId(gGroupSiteRelateDto.getParentId());
                    item.setProjectId(gGroupSiteRelateDto.getProjectId());
                })
                .collect(Collectors.toList()))? 1 : 0;
    }

    /**
     * 搜索站点列表
     */
    @Override
    public List<GSites> searchGSitesList(GSites gSites) {
        return new LambdaQueryChainWrapper<>(gSitesMapper)
                .select(GSites::getId, GSites::getName, GSites::getType, GSites::getIcon)
                .eq(GSites::getProjectId, gSites.getProjectId())
                .like(GSites::getName, gSites.getSearchValue())
                .list();
    }

}

