package com.ruoyi.bst.area.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

import org.locationtech.jts.geom.Geometry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import com.github.pagehelper.PageHelper;
import com.ruoyi.bst.agreement.domain.enums.AgreementType;
import com.ruoyi.bst.agreement.service.AgreementService;
import com.ruoyi.bst.area.domain.Area;
import com.ruoyi.bst.area.domain.AreaQuery;
import com.ruoyi.bst.area.domain.AreaVO;
import com.ruoyi.bst.area.domain.enums.AreaStatus;
import com.ruoyi.bst.area.domain.vo.LocationAreaVO;
import com.ruoyi.bst.area.mapper.AreaMapper;
import com.ruoyi.bst.area.service.AreaDashboard;
import com.ruoyi.bst.area.service.AreaService;
import com.ruoyi.bst.area.service.AreaValidator;
import com.ruoyi.bst.area.utils.AreaUtil;
import com.ruoyi.bst.areaJoin.domain.enums.AreaJoinPermission;
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
import com.ruoyi.bst.areaSub.service.AreaSubService;
import com.ruoyi.common.domain.vo.LongIntegerVO;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.common.utils.map.GeoUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 运营区Service业务层处理
 *
 * @author ruoyi
 * @date 2025-03-14
 */
@Service
@Slf4j
public class AreaServiceImpl implements AreaService
{
    @Autowired
    private AreaMapper areaMapper;

    @Autowired
    private AreaSubService areaSubService;

    @Autowired
    private AgreementService agreementService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private AreaDashboard areaDashboard;

    @Autowired
    private AreaValidator areaValidator;

    /**
     * 查询运营区
     *
     * @param id 运营区主键
     * @return 运营区
     */
    @Override
    public AreaVO selectAreaById(Long id, boolean scope)
    {
        if (id == null) {
            return null;
        }
        AreaQuery query = new AreaQuery();
        query.setId(id);
        query.setScope(scope);
        query.addAreaPermission(AreaJoinPermission.AREA_VIEW.getCode());
        return this.selectOne(query);
    }

    @Override
    public AreaVO selectOne(AreaQuery query) {
        PageHelper.startPage(1, 1);
        List<AreaVO> list = areaMapper.selectAreaList(query);
        return CollectionUtils.firstElement(list);
    }

    @Override
    public Long selectAreaByStoreId(Long storeId) {
        return areaMapper.selectAreaByStoreId(storeId);
    }

    @Override
    public List<AreaVO> selectSimpleList(AreaQuery query) {
        return areaMapper.selectSimpleList(query);
    }

    /**
     * 查询运营区列表
     *
     * @param area 运营区
     * @return 运营区
     */
    @Override
    public List<AreaVO> selectAreaList(AreaQuery area)
    {
        return areaMapper.selectAreaList(area);
    }

    /**
     * 新增运营区
     *
     * @param area 运营区
     * @return 结果
     */
    @Override
    public int insertArea(Area area)
    {
        // 将边界值转Geometry对象
        if (area.getBoundaryStr() != null) {
            Geometry geometry = GeoUtils.toGeometry(area.getBoundaryStr());
            area.setBoundary(GeoUtils.wkt(geometry));
        }
        area.setCreateTime(DateUtils.getNowDate());

        Integer result = transactionTemplate.execute(status -> {

            int rows = areaMapper.insertArea(area);
            if (rows > 0) {
                // 复制一份租赁协议到运营区内
                int copy = agreementService.copyTemplate(AgreementType.RENT, area.getId());
                ServiceUtil.assertion(copy != 1, "复制协议模板失败");
            }

            return rows;
        });

        return result == null ? 0 : result;
    }

    /**
     * 修改运营区
     *
     * @param area 运营区
     * @return 结果
     */
    @Override
    public int updateArea(Area area)
    {
        // 将边界值转Geometry对象
        if (area.getBoundaryStr() != null) {
            Geometry geometry = GeoUtils.toGeometry(area.getBoundaryStr());
            area.setBoundary(GeoUtils.wkt(geometry));
        }
        Integer result = transactionTemplate.execute(status -> {
            int rows = areaMapper.updateArea(area);

            // 若修改运营商ID，则校验运营商的分成
            if (area.getUserId() != null) {
                areaValidator.checkPoint(area.getId());
            }

            return rows;
        });

        return result == null ? 0 : result;
    }

    /**
     * 批量删除运营区
     *
     * @param ids 需要删除的运营区主键
     * @return 结果
     */
    @Override
    public int deleteAreaByIds(Long[] ids)
    {
        return areaMapper.deleteAreaByIds(ids);
    }

    /**
     * 删除运营区信息
     *
     * @param id 运营区主键
     * @return 结果
     */
    @Override
    public int deleteAreaById(Long id)
    {
        return areaMapper.deleteAreaById(id);
    }

    /**
     * 逻辑删除运营区
     *
     * @param ids 需要删除的运营区主键集合
     * @return 结果
     */
    @Override
    public int logicDel(List<Long> ids)
    {
        return areaMapper.logicDel(ids);
    }


    @Override
    public LocationAreaVO selectLocationArea(BigDecimal lon, BigDecimal lat, Long areaId) {
        if (lon == null || lat == null || areaId == null) {
            return null;
        }
        // 查询运营区
        AreaVO area = this.selectAreaById(areaId);
        if (area == null) {
            return null;
        }
        // 查询运营区内的禁行区
        List<AreaSubVO> noRidingList = areaSubService.selectNoRidingListByAreaId(areaId);

        return AreaUtil.getLocationArea(lon, lat, area, noRidingList);
    }

    @Override
    public List<Long> selectIdList(AreaQuery query) {
        return areaMapper.selectIdByQuery(query);
    }

    @Override
    public AreaVO selectNearBy(AreaQuery query) {
        if (query.getCenter() == null) {
            log.error("中心坐标不能为空");
            return null;
        }
        if (query.getCenter().size() != 2) {
            log.error("中心坐标格式错误，必须包含经度和纬度");
            return null;
        }
        query.setStatus(AreaStatus.ENABLED.getCode());

        // 按设备数量排序，查询附近的运营区
        Long areaId = query.getId();
        query.setId(null);
        List<LongIntegerVO> list = areaDashboard.selectMaxOfDeviceCountAreaId(query);
        if (CollectionUtils.isEmptyElement(list)) {
            return null;
        }

        // 如果有传运营区ID，则优先找运营区
        LongIntegerVO max = null;
        if (areaId != null) {
            max = list.stream().filter(item -> Objects.equals(item.getKey(), areaId)).findFirst().orElse(null);
        }
        // 若没有找到对应运营区，则取设备数量最多的运营区
        if (max == null) {
            max = list.get(0);
        }

        // 查询运营区详情
        return this.selectAreaById(max.getKey());
    }
}
