package com.seer.teach.common.service.impl;

import com.seer.teach.common.convert.CityConvert;
import com.seer.teach.common.entity.CityEntity;
import com.seer.teach.common.entity.ProvinceEntity;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.resp.AddressIdResp;
import com.seer.teach.common.resp.CityResp;
import com.seer.teach.common.resp.IpAddressResp;
import com.seer.teach.common.service.RegionAddressService;
import com.seer.teach.common.service.CityService;
import com.seer.teach.common.service.ProvinceService;
import com.seer.teach.common.utils.AssertUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 地址服务实现类，提供省份、城市信息查询及 IP 定位相关功能。
 *
 * @author Captain
 * @since 2025-11-22 10:17
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RegionAddressServiceImpl implements RegionAddressService {

    private final CityService cityService;

    private final ProvinceService provinceService;

    private final Ip2RegionService ip2RegionService;

    /**
     * 根据省份ID获取该省下的所有城市列表。
     *
     * @param provinceId 省份ID
     * @return 城市响应对象列表
     */
    @Override
    public List<CityResp> getCitiesByProvinceId(Integer provinceId) {
        List<CityEntity> list = cityService.lambdaQuery()
                .eq(CityEntity::getProvinceId, provinceId)
                .list();
        AssertUtils.notEmpty(list, ResultCodeEnum.CITY_NOT_FOUND);
        return CityConvert.INSTANCE.toCityRespList(list);
    }

    /**
     * 根据省份ID获取对应的省份实体。
     *
     * @param provinceId 省份ID
     * @return 省份实体对象
     */
    @Override
    public ProvinceEntity getProvinceById(Integer provinceId) {
        ProvinceEntity province = provinceService.lambdaQuery()
                .eq(ProvinceEntity::getId, provinceId)
                .one();
        AssertUtils.notNull(province, ResultCodeEnum.PROVINCE_NOT_EXIST);
        return province;
    }

    /**
     * 根据城市ID获取其所属的省份实体。
     *
     * @param cityId 城市ID
     * @return 所属省份实体，若未找到则返回null
     */
    @Override
    public ProvinceEntity getProvinceByCityId(Integer cityId) {
        CityEntity city = cityService.getById(cityId);
        // 若城市存在且有省份ID，则尝试获取对应省份
        if (Objects.nonNull(city) && Objects.nonNull(city.getProvinceId())) {
            return provinceService.getById(city.getProvinceId());
        }
        return null;
    }

    /**
     * 根据城市ID获取城市实体。
     *
     * @param cityId 城市ID
     * @return 城市实体对象
     */
    @Override
    public CityEntity getCityById(Integer cityId) {
        CityEntity one = cityService.getById(cityId);
        AssertUtils.notNull(one, ResultCodeEnum.CITY_NOT_FOUND);
        return cityService.getById(cityId);
    }

    /**
     * 根据城市名称获取城市实体。
     *
     * @param cityName 城市名称
     * @return 匹配的城市实体对象
     */
    @Override
    public CityEntity getCityByCityName(String cityName) {
        CityEntity cityData = cityService.lambdaQuery()
                .eq(CityEntity::getCity, cityName)
                .one();
        AssertUtils.notNull(cityData, ResultCodeEnum.CITY_UPDATE_ERROR);
        return cityData;
    }

    /**
     * 根据省份ID获取该省下所有的城市实体列表。
     *
     * @param provinceId 省份ID
     * @return 城市实体列表
     */
    @Override
    public List<CityEntity> getCitysByProvinceId(Integer provinceId) {
        List<CityEntity> list = cityService.lambdaQuery()
                .eq(CityEntity::getProvinceId, provinceId)
                .list();
        AssertUtils.notEmpty(list, ResultCodeEnum.CITY_NOT_FOUND);
        return list;
    }

    /**
     * 根据IP地址解析出对应的省份和城市，并返回它们的ID。
     *
     * @param ipAddress IP地址字符串
     * @return 封装了省份ID与城市ID的响应对象
     */
    @Override
    public AddressIdResp getAddressId(String ipAddress) {
        IpAddressResp ipAddressResp = ip2RegionService.getProvinceCityByIp(ipAddress);
        AssertUtils.notNull(ipAddressResp, ResultCodeEnum.IP_NOT_FOUND);

        ProvinceEntity province = provinceService.lambdaQuery()
                .eq(ProvinceEntity::getProvince, ipAddressResp.getProvince())
                .one();
        AssertUtils.notNull(province, ResultCodeEnum.PROVINCE_NOT_EXIST);

        CityEntity city = cityService.lambdaQuery()
                .eq(CityEntity::getCity, ipAddressResp.getCity())
                .one();
        AssertUtils.notNull(city, ResultCodeEnum.CITY_NOT_FOUND);
        log.info("IP地址地域信息：Ip:{} Province:{} City:{}", ipAddress, province.getProvince(), city.getCity());
        return new AddressIdResp(province.getId(), city.getId());
    }

    /**
     * 从HTTP请求中提取客户端的真实IP地址。
     *
     * @param request HTTP请求对象
     * @return 提取到的IP地址字符串
     */
    @Override
    public String getIpAddress(HttpServletRequest request) {
        String ip = ip2RegionService.extractClientIp(request);
        AssertUtils.notEmpty(ip, ResultCodeEnum.IP_NOT_FOUND);
        return ip2RegionService.extractClientIp(request);
    }

    /**
     * 获取所有省份信息
     * @return 所有省份信息
     */
    @Override
    public List<ProvinceEntity> getAllProvinces() {
        List<ProvinceEntity> list = provinceService.list();
        AssertUtils.notEmpty(list, ResultCodeEnum.PROVINCE_NOT_EXIST);
        return list;
    }

    /**
     *  获取所有城市信息
     * @return 所有城市信息
     */
    @Override
    public List<CityEntity> getAllCitys() {
        List<CityEntity> list = cityService.list();
        AssertUtils.notEmpty(list, ResultCodeEnum.CITY_NOT_FOUND);
        return list;
    }
}
