using System.Text.Json;
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Models.Auth;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Core.Services;

/// <summary>
/// IP地理位置服务实现 - 使用高德地图API
/// </summary>
public class IpLocationService : IIpLocationService
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<IpLocationService> _logger;
    private readonly AmapSettings _amapSettings;

    // 高德地图IP定位API端点
    private const string AmapIpLocationUrl = "https://restapi.amap.com/v3/ip";

    public IpLocationService(HttpClient httpClient, ILogger<IpLocationService> logger, AmapSettings amapSettings)
    {
        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        _amapSettings = amapSettings ?? throw new ArgumentNullException(nameof(amapSettings));
    }

    /// <summary>
    /// 根据IP地址获取地理位置信息
    /// </summary>
    /// <param name="ip">IP地址</param>
    /// <returns>IP地理位置结果</returns>
    public async Task<IpLocationResult> GetLocationAsync(string ip)
    {
        if (string.IsNullOrWhiteSpace(ip))
        {
            _logger.LogWarning("GetLocationAsync called with empty IP address");
            return new IpLocationResult
            {
                Success = false,
                ErrorMessage = "IP地址不能为空"
            };
        }

        // 检查是否为本地IP地址
        if (IsLocalIpAddress(ip))
        {
            _logger.LogInformation("Local IP address detected: {Ip}, returning empty location", ip);
            return new IpLocationResult
            {
                Success = true,
                Province = null,
                City = null,
                Adcode = null
            };
        }

        try
        {
            var url = $"{AmapIpLocationUrl}?key={_amapSettings.ApiKey}&ip={ip}";
            
            _logger.LogInformation("Calling Amap API to get location for IP: {Ip}", ip);
            
            var response = await _httpClient.GetAsync(url);
            var content = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError("Amap API returned error status {StatusCode}: {Content}", response.StatusCode, content);
                return new IpLocationResult
                {
                    Success = false,
                    ErrorMessage = "高德地图API调用失败"
                };
            }

            using var jsonDoc = JsonDocument.Parse(content);
            var root = jsonDoc.RootElement;

            // 检查API返回状态
            var status = root.TryGetProperty("status", out var statusProp) ? statusProp.GetString() : null;
            if (status != "1")
            {
                var info = root.TryGetProperty("info", out var infoProp) ? infoProp.GetString() : "未知错误";
                _logger.LogWarning("Amap API returned error: {Info}", info);
                return new IpLocationResult
                {
                    Success = false,
                    ErrorMessage = $"IP定位失败: {info}"
                };
            }

            // 提取省份、城市和区域编码
            var province = GetStringOrNull(root, "province");
            var city = GetStringOrNull(root, "city");
            var adcode = GetStringOrNull(root, "adcode");

            _logger.LogInformation("Successfully retrieved location for IP {Ip}: Province={Province}, City={City}, Adcode={Adcode}", 
                ip, province, city, adcode);

            return new IpLocationResult
            {
                Success = true,
                Province = province,
                City = city,
                Adcode = adcode
            };
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "HTTP request error when calling Amap API for IP: {Ip}", ip);
            return new IpLocationResult
            {
                Success = false,
                ErrorMessage = "网络连接失败"
            };
        }
        catch (JsonException ex)
        {
            _logger.LogError(ex, "JSON parsing error when processing Amap API response for IP: {Ip}", ip);
            return new IpLocationResult
            {
                Success = false,
                ErrorMessage = "响应数据格式错误"
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unexpected error when calling Amap API for IP: {Ip}", ip);
            return new IpLocationResult
            {
                Success = false,
                ErrorMessage = "系统错误"
            };
        }
    }

    /// <summary>
    /// 检查是否为本地IP地址
    /// </summary>
    private static bool IsLocalIpAddress(string ip)
    {
        return ip == "127.0.0.1" 
            || ip == "::1" 
            || ip.StartsWith("192.168.") 
            || ip.StartsWith("10.") 
            || ip.StartsWith("172.16.")
            || ip.StartsWith("172.17.")
            || ip.StartsWith("172.18.")
            || ip.StartsWith("172.19.")
            || ip.StartsWith("172.20.")
            || ip.StartsWith("172.21.")
            || ip.StartsWith("172.22.")
            || ip.StartsWith("172.23.")
            || ip.StartsWith("172.24.")
            || ip.StartsWith("172.25.")
            || ip.StartsWith("172.26.")
            || ip.StartsWith("172.27.")
            || ip.StartsWith("172.28.")
            || ip.StartsWith("172.29.")
            || ip.StartsWith("172.30.")
            || ip.StartsWith("172.31.");
    }

    /// <summary>
    /// 从JSON元素中获取字符串值，如果是空数组则返回null
    /// </summary>
    private static string? GetStringOrNull(JsonElement element, string propertyName)
    {
        if (!element.TryGetProperty(propertyName, out var prop))
        {
            return null;
        }

        // 高德API在某些情况下会返回空数组[]而不是字符串
        if (prop.ValueKind == JsonValueKind.Array)
        {
            return null;
        }

        if (prop.ValueKind == JsonValueKind.String)
        {
            var value = prop.GetString();
            return string.IsNullOrWhiteSpace(value) ? null : value;
        }

        return null;
    }
}
