"""
Weather Tools - 天气查询工具

提供根据经纬度查询天气信息的功能，使用Open-Meteo API
"""

import requests
import json
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any

# 导入地理编码库
try:
    from geopy.geocoders import Nominatim
    GEOPY_AVAILABLE = True
    # 创建地理编码器实例
    geolocator = Nominatim(user_agent="FlightTicketMCP_WeatherApp")
except ImportError:
    GEOPY_AVAILABLE = False
    geolocator = None
    logger.warning("geopy库未安装，将仅支持预设城市的天气查询")

# 初始化日志器
logger = logging.getLogger(__name__)

def getWeatherByLocation(latitude: float, longitude: float, start_date: str = None, end_date: str = None) -> Dict[str, Any]:
    """
    根据经纬度查询天气信息
    
    Args:
        latitude: 纬度
        longitude: 经度  
        start_date: 开始日期 (YYYY-MM-DD格式)，可选，默认为前一天
        end_date: 结束日期 (YYYY-MM-DD格式)，可选，默认为后一天
        
    Returns:
        包含天气查询结果的字典
    """
    logger.info(f"开始查询天气信息: 纬度={latitude}, 经度={longitude}, 开始日期={start_date}, 结束日期={end_date}")
    
    try:
        # 验证输入参数
        if latitude is None or longitude is None:
            logger.warning("经纬度参数不能为空")
            return {
                "status": "error",
                "message": "经纬度参数不能为空",
                "error_code": "INVALID_PARAMS"
            }
        
        # 验证经纬度范围
        if not (-90 <= latitude <= 90):
            logger.warning(f"纬度超出有效范围: {latitude}")
            return {
                "status": "error", 
                "message": f"纬度必须在-90到90之间，当前值: {latitude}",
                "error_code": "INVALID_LATITUDE"
            }
            
        if not (-180 <= longitude <= 180):
            logger.warning(f"经度超出有效范围: {longitude}")
            return {
                "status": "error",
                "message": f"经度必须在-180到180之间，当前值: {longitude}",
                "error_code": "INVALID_LONGITUDE"
            }
        
        # 设置默认日期（今天和明天，共两天）
        now = datetime.now()
        if start_date is None:
            # 默认从今天开始
            start_date = now.strftime('%Y-%m-%d')
        
        if end_date is None:
            # 默认到明天结束
            default_end = now + timedelta(days=1)
            end_date = default_end.strftime('%Y-%m-%d')
        
        # 验证日期格式
        try:
            start_dt = datetime.strptime(start_date, '%Y-%m-%d')
            end_dt = datetime.strptime(end_date, '%Y-%m-%d')
            logger.debug(f"日期解析成功: {start_dt} 到 {end_dt}")
        except ValueError as ve:
            logger.warning(f"日期格式错误: start_date={start_date}, end_date={end_date}")
            return {
                "status": "error",
                "message": "日期格式不正确，请使用YYYY-MM-DD格式",
                "error_code": "INVALID_DATE_FORMAT"
            }
        
        # 验证日期范围
        if start_dt > end_dt:
            logger.warning(f"开始日期晚于结束日期: {start_date} > {end_date}")
            return {
                "status": "error",
                "message": "开始日期不能晚于结束日期",
                "error_code": "INVALID_DATE_RANGE"
            }
        
        # 构建API请求URL
        base_url = "https://api.open-meteo.com/v1/forecast"
        params = {
            "latitude": latitude,
            "longitude": longitude,
            "hourly": "temperature_2m",
            "models": "cma_grapes_global",
            "timezone": "Asia/Shanghai",
            "start_date": start_date,
            "end_date": end_date
        }
        
        logger.info(f"请求Open-Meteo API: {base_url}")
        logger.debug(f"请求参数: {params}")
        
        try:
            # 发送HTTP请求
            response = requests.get(base_url, params=params, timeout=30)
            response.raise_for_status()
            
            weather_data = response.json()
            logger.debug(f"API响应数据: {json.dumps(weather_data, indent=2, ensure_ascii=False)}")
            
            # 调试：检查温度数据质量
            if "hourly" in weather_data and "temperature_2m" in weather_data["hourly"]:
                temps = weather_data["hourly"]["temperature_2m"]
                none_count = sum(1 for temp in temps if temp is None)
                valid_count = len(temps) - none_count
                logger.debug(f"温度数据质量检查: 总数据点={len(temps)}, 有效数据点={valid_count}, None值数量={none_count}")
            
            # 格式化结果
            result = {
                "status": "success",
                "latitude": weather_data.get("latitude"),
                "longitude": weather_data.get("longitude"),
                "timezone": weather_data.get("timezone"),
                "timezone_abbreviation": weather_data.get("timezone_abbreviation"),
                "elevation": weather_data.get("elevation"),
                "start_date": start_date,
                "end_date": end_date,
                "hourly_units": weather_data.get("hourly_units", {}),
                "hourly_data": weather_data.get("hourly", {}),
                "formatted_output": _format_weather_result(weather_data, latitude, longitude, start_date, end_date),
                "query_time": datetime.now().isoformat()
            }
            
            # 添加温度统计信息
            if "hourly" in weather_data and "temperature_2m" in weather_data["hourly"]:
                temperatures = weather_data["hourly"]["temperature_2m"]
                if temperatures:
                    # 过滤掉None值
                    valid_temperatures = [temp for temp in temperatures if temp is not None]
                    if valid_temperatures:
                        result["temperature_statistics"] = {
                            "min_temperature": min(valid_temperatures),
                            "max_temperature": max(valid_temperatures),
                            "avg_temperature": round(sum(valid_temperatures) / len(valid_temperatures), 1),
                            "data_points": len(temperatures),
                            "valid_data_points": len(valid_temperatures)
                        }
                    else:
                        logger.warning("所有温度数据都为None值")
                        result["temperature_statistics"] = {
                            "error": "无有效温度数据",
                            "data_points": len(temperatures),
                            "valid_data_points": 0
                        }
            
            logger.info(f"天气查询成功: 纬度={latitude}, 经度={longitude}")
            return result
            
        except requests.exceptions.RequestException as re:
            logger.error(f"API请求失败: {str(re)}", exc_info=True)
            return {
                "status": "error",
                "message": f"天气API请求失败: {str(re)}",
                "error_code": "API_REQUEST_FAILED"
            }
            
        except json.JSONDecodeError as je:
            logger.error(f"API响应解析失败: {str(je)}", exc_info=True)
            return {
                "status": "error",
                "message": f"天气API响应格式错误: {str(je)}",
                "error_code": "API_RESPONSE_INVALID"
            }
            
    except Exception as e:
        logger.error(f"查询天气信息失败: {str(e)}", exc_info=True)
        return {
            "status": "error",
            "message": f"查询天气信息失败: {str(e)}",
            "error_code": "WEATHER_QUERY_FAILED"
        }


def _format_weather_result(weather_data: Dict[str, Any], latitude: float, longitude: float, start_date: str, end_date: str) -> str:
    """
    格式化天气查询结果
    
    Args:
        weather_data: API返回的天气数据
        latitude: 纬度
        longitude: 经度
        start_date: 开始日期
        end_date: 结束日期
        
    Returns:
        格式化后的字符串
    """
    try:
        output = []
        output.append("🌤️ 天气查询结果")
        output.append(f"📍 位置: 纬度 {weather_data.get('latitude', latitude)}, 经度 {weather_data.get('longitude', longitude)}")
        output.append(f"📅 查询时间段: {start_date} 到 {end_date}")
        output.append(f"🌍 时区: {weather_data.get('timezone', 'N/A')} ({weather_data.get('timezone_abbreviation', 'N/A')})")
        
        if "elevation" in weather_data:
            output.append(f"⛰️ 海拔: {weather_data['elevation']}米")
        
        output.append("")
        
        # 处理小时温度数据
        if "hourly" in weather_data and "temperature_2m" in weather_data["hourly"]:
            times = weather_data["hourly"].get("time", [])
            temperatures = weather_data["hourly"].get("temperature_2m", [])
            
            if times and temperatures:
                # 按日期分组显示
                daily_data = {}
                for time_str, temp in zip(times, temperatures):
                    try:
                        dt = datetime.fromisoformat(time_str.replace('T', ' '))
                        date_key = dt.strftime('%Y-%m-%d')
                        hour = dt.strftime('%H:%M')
                        
                        if date_key not in daily_data:
                            daily_data[date_key] = []
                        daily_data[date_key].append((hour, temp))
                    except:
                        continue
                
                # 显示每日数据
                for date, hourly_temps in daily_data.items():
                    output.append(f"📆 {date}")
                    
                    # 计算当日统计
                    day_temps = [temp for _, temp in hourly_temps if temp is not None]
                    if day_temps:
                        min_temp = min(day_temps)
                        max_temp = max(day_temps)
                        avg_temp = sum(day_temps) / len(day_temps)
                        output.append(f"    🌡️ 温度范围: {min_temp:.1f}°C ~ {max_temp:.1f}°C (平均: {avg_temp:.1f}°C)")
                    else:
                        output.append(f"    ❌ 当日无有效温度数据")
                    
                    # 显示部分小时数据（每4小时一次）
                    sample_data = hourly_temps[::4]  # 每4小时取一个样本
                    for hour, temp in sample_data[:6]:  # 最多显示6个时间点
                        if temp is not None:
                            output.append(f"    {hour}: {temp}°C")
                        else:
                            output.append(f"    {hour}: 无数据")
                    
                    output.append("")
                
                # 整体统计
                all_temps = [temp for _, temp in temperatures if temp is not None]
                if all_temps:
                    output.append("📊 整体统计:")
                    output.append(f"    最低温度: {min(all_temps):.1f}°C")
                    output.append(f"    最高温度: {max(all_temps):.1f}°C") 
                    output.append(f"    平均温度: {sum(all_temps)/len(all_temps):.1f}°C")
                    output.append(f"    数据点数: {len(times)}个")
        else:
            output.append("❌ 未获取到温度数据")
        
        return "\n".join(output)
        
    except Exception as e:
        logger.error(f"格式化天气结果失败: {str(e)}", exc_info=True)
        return f"天气数据格式化失败: {str(e)}" 

# 主要城市经纬度数据
CITY_COORDINATES = {
    "北京": {"latitude": 39.9042, "longitude": 116.4074, "name": "北京"},
    "上海": {"latitude": 31.2304, "longitude": 121.4737, "name": "上海"},
    "广州": {"latitude": 23.1291, "longitude": 113.2644, "name": "广州"},
    "深圳": {"latitude": 22.5431, "longitude": 114.0579, "name": "深圳"},
    "成都": {"latitude": 30.5728, "longitude": 104.0668, "name": "成都"},
    "武汉": {"latitude": 30.5928, "longitude": 114.3055, "name": "武汉"},
    "西安": {"latitude": 34.3416, "longitude": 108.9398, "name": "西安"},
    "杭州": {"latitude": 30.2741, "longitude": 120.1551, "name": "杭州"},
    "重庆": {"latitude": 29.5647, "longitude": 106.5507, "name": "重庆"},
    "天津": {"latitude": 39.3434, "longitude": 117.3616, "name": "天津"},
    "南京": {"latitude": 32.0603, "longitude": 118.7969, "name": "南京"},
    "青岛": {"latitude": 36.0986, "longitude": 120.3719, "name": "青岛"},
    "大连": {"latitude": 38.9140, "longitude": 121.6147, "name": "大连"},
    "宁波": {"latitude": 29.8683, "longitude": 121.5440, "name": "宁波"},
    "厦门": {"latitude": 24.4798, "longitude": 118.0819, "name": "厦门"},
    "福州": {"latitude": 26.0745, "longitude": 119.2965, "name": "福州"},
    "无锡": {"latitude": 31.4912, "longitude": 120.3124, "name": "无锡"},
    "合肥": {"latitude": 31.8206, "longitude": 117.2272, "name": "合肥"},
    "昆明": {"latitude": 25.0389, "longitude": 102.7183, "name": "昆明"},
    "哈尔滨": {"latitude": 45.8038, "longitude": 126.5349, "name": "哈尔滨"},
    "沈阳": {"latitude": 41.8057, "longitude": 123.4315, "name": "沈阳"},
    "长春": {"latitude": 43.8171, "longitude": 125.3235, "name": "长春"},
    "石家庄": {"latitude": 38.0428, "longitude": 114.5149, "name": "石家庄"},
    "长沙": {"latitude": 28.2282, "longitude": 112.9388, "name": "长沙"},
    "郑州": {"latitude": 34.7466, "longitude": 113.6254, "name": "郑州"},
    "南昌": {"latitude": 28.6820, "longitude": 115.8581, "name": "南昌"},
    "贵阳": {"latitude": 26.6470, "longitude": 106.6302, "name": "贵阳"},
    "兰州": {"latitude": 36.0611, "longitude": 103.8343, "name": "兰州"},
    "海口": {"latitude": 20.0458, "longitude": 110.3417, "name": "海口"},
    "三亚": {"latitude": 18.2528, "longitude": 109.5122, "name": "三亚"},
    "银川": {"latitude": 38.4872, "longitude": 106.2309, "name": "银川"},
    "西宁": {"latitude": 36.6171, "longitude": 101.7782, "name": "西宁"},
    "呼和浩特": {"latitude": 40.8414, "longitude": 111.7519, "name": "呼和浩特"},
    "乌鲁木齐": {"latitude": 43.8256, "longitude": 87.6168, "name": "乌鲁木齐"},
    "拉萨": {"latitude": 29.6625, "longitude": 91.1112, "name": "拉萨"},
    "南宁": {"latitude": 22.8170, "longitude": 108.3669, "name": "南宁"},
    # 港澳台
    "香港": {"latitude": 22.3193, "longitude": 114.1694, "name": "香港"},
    "澳门": {"latitude": 22.1987, "longitude": 113.5439, "name": "澳门"},
    "台北": {"latitude": 25.0330, "longitude": 121.5654, "name": "台北"},
}

def getWeatherByCity(city_name: str, start_date: str = None, end_date: str = None) -> Dict[str, Any]:
    """
    根据城市名查询天气信息
    
    Args:
        city_name: 城市名（如：武汉、北京、上海等，支持全球任意城市）
        start_date: 开始日期 (YYYY-MM-DD格式)，可选，默认为今天
        end_date: 结束日期 (YYYY-MM-DD格式)，可选，默认为明天
        
    Returns:
        包含天气查询结果的字典
    """
    logger.info(f"根据城市名查询天气: {city_name}")
    
    try:
        # 清理输入的城市名
        city_name = city_name.strip()
        city_coord = None
        city_display_name = city_name
        coordinate_source = "unknown"
        
        # 方法1：首先尝试从预设字典查找（更快更准确）
        search_keys = [
            city_name,
            city_name.replace("市", ""),  # 去掉"市"后缀
            city_name.replace("省", ""),  # 去掉"省"后缀
        ]
        
        for key in search_keys:
            if key in CITY_COORDINATES:
                city_coord = CITY_COORDINATES[key]
                city_display_name = city_coord["name"]
                coordinate_source = "preset_dict"
                logger.info(f"从预设字典找到城市 '{city_name}' 的坐标: 纬度={city_coord['latitude']}, 经度={city_coord['longitude']}")
                break
        
        #如果预设字典中没有，尝试使用geopy进行地理编码
        if not city_coord and GEOPY_AVAILABLE and geolocator:
            try:
                logger.info(f"使用geopy查找城市 '{city_name}' 的坐标...")
                location = geolocator.geocode(city_name, timeout=10)
                
                if location:
                    city_coord = {
                        "latitude": location.latitude,
                        "longitude": location.longitude,
                        "name": city_name
                    }
                    city_display_name = location.address if location.address else city_name
                    coordinate_source = "geopy"
                    logger.info(f"通过geopy找到城市 '{city_name}' 的坐标: 纬度={city_coord['latitude']}, 经度={city_coord['longitude']}")
                    logger.debug(f"geopy返回的完整地址: {location.address}")
                else:
                    logger.warning(f"geopy无法找到城市 '{city_name}' 的坐标")
                    
            except Exception as geo_e:
                logger.warning(f"geopy查询失败: {str(geo_e)}")
        
        # 如果两种方法都没有找到坐标
        if not city_coord:
            error_message = f"无法找到城市 '{city_name}' 的坐标信息。"
            if GEOPY_AVAILABLE:
                error_message += "请检查城市名称是否正确。"
            else:
                error_message += f"当前仅支持预设城市：不支持"
            
            logger.warning(error_message)
            return {
                "status": "error",
                "message": error_message,
                "error_code": "CITY_NOT_FOUND",
                "coordinate_source": coordinate_source,
                "geopy_available": GEOPY_AVAILABLE
            }
        
        # 调用原有的经纬度查询函数
        result = getWeatherByLocation(
            latitude=city_coord["latitude"],
            longitude=city_coord["longitude"],
            start_date=start_date,
            end_date=end_date
        )
        
        # 在结果中添加城市信息
        if result.get("status") == "success":
            result["city_name"] = city_display_name
            result["city_input"] = city_name
            result["coordinate_source"] = coordinate_source
            
            # 更新格式化输出，添加城市名称
            if "formatted_output" in result:
                formatted_lines = result["formatted_output"].split('\n')
                if formatted_lines:
                    # 替换第一行，添加城市名称
                    formatted_lines[0] = f"🌤️ {city_display_name}天气查询结果"
                    result["formatted_output"] = '\n'.join(formatted_lines)
        
        return result
        
    except Exception as e:
        logger.error(f"根据城市名查询天气失败: {str(e)}", exc_info=True)
        return {
            "status": "error", 
            "message": f"查询城市 '{city_name}' 天气失败: {str(e)}",
            "error_code": "CITY_WEATHER_QUERY_FAILED"
        }

 