import tkinter as tk
from tkinter import messagebox
import requests

# ======================== 天气查询核心 ========================

def query_weather(city):
    """
    调用 wttr.in 免费天气 API，返回解析后的天气数据字典。
    若失败则抛出异常。
    """
    url = f"https://wttr.in/{city}?format=j1&lang=zh"
    headers = {"User-Agent": "WeatherApp/1.0"}
    resp = requests.get(url, headers=headers, timeout=10)
    resp.raise_for_status()
    data = resp.json()

    # 当前天气
    current = data["current_condition"][0]
    current_weather = {
        "city": data["nearest_area"][0]["areaName"][0]["value"],
        "temp": current["temp_C"],
        "feels_like": current["FeelsLikeC"],
        "desc": current["lang_zh"][0]["value"] if "lang_zh" in current else current["weatherDesc"][0]["value"],
        "humidity": current["humidity"],
        "wind_speed": current["windspeedKmph"],
        "wind_dir": current["winddir16Point"],
        "visibility": current["visibility"],
        "uv_index": current["uvIndex"],
    }

    # 未来预报
    forecast_list = []
    for day in data.get("weather", [])[:3]:
        forecast_list.append({
            "date": day["date"],
            "max_temp": day["maxtempC"],
            "min_temp": day["mintempC"],
            "desc": day["hourly"][4]["lang_zh"][0]["value"] if "lang_zh" in day["hourly"][4] else day["hourly"][4]["weatherDesc"][0]["value"],
            "sunrise": day["astronomy"][0]["sunrise"],
            "sunset": day["astronomy"][0]["sunset"],
        })

    return {"current": current_weather, "forecast": forecast_list}


# ======================== 天气图标映射 ========================

WEATHER_ICONS = {
    "晴": "☀️", "晴转多云": "🌤️", "多云": "⛅", "阴": "☁️",
    "小雨": "🌦️", "中雨": "🌧️", "大雨": "🌧️", "暴雨": "⛈️",
    "雷阵雨": "⛈️", "阵雨": "🌦️", "小雪": "🌨️", "中雪": "🌨️",
    "大雪": "❄️", "雾": "🌫️", "霾": "😷",
}

def get_icon(desc):
    """根据天气描述返回对应 emoji"""
    for key, icon in WEATHER_ICONS.items():
        if key in desc:
            return icon
    return "🌈"


# ======================== 界面构建 ========================

class WeatherApp:
    def __init__(self, root):
        self.root = root
        self.root.title("🌤️ 天气查询小工具")
        self.root.geometry("500x680")
        self.root.resizable(False, False)
        self.root.configure(bg="#eef5ff")

        self._build_title()
        self._build_search_bar()
        self._build_result_area()
        self._build_footer()

        # 绑定回车键快捷查询
        self.root.bind("<Return>", lambda e: self.do_query())

    # ---------- 标题栏 ----------
    def _build_title(self):
        frame = tk.Frame(self.root, bg="#3b82f6", height=65)
        frame.pack(fill=tk.X)
        frame.pack_propagate(False)
        tk.Label(frame, text="🌤️  天气查询小工具",
                 font=("微软雅黑", 20, "bold"), fg="white", bg="#3b82f6").pack(expand=True)

    # ---------- 搜索栏 ----------
    def _build_search_bar(self):
        frame = tk.Frame(self.root, bg="#eef5ff")
        frame.pack(padx=20, pady=(15, 5), fill=tk.X)

        tk.Label(frame, text="城市:", font=("微软雅黑", 12), bg="#eef5ff").pack(side=tk.LEFT)

        self.city_var = tk.StringVar(value="北京")
        self.city_entry = tk.Entry(frame, textvariable=self.city_var, width=16,
                                    font=("微软雅黑", 13), justify="center",
                                    relief="solid", bd=1)
        self.city_entry.pack(side=tk.LEFT, padx=(5, 10), ipady=3)

        btn = tk.Button(frame, text="🔍 查询", font=("微软雅黑", 11, "bold"),
                        bg="#3b82f6", fg="white", activebackground="#2563eb",
                        relief="flat", cursor="hand2", padx=15,
                        command=self.do_query)
        btn.pack(side=tk.LEFT)

    # ---------- 结果展示区 ----------
    def _build_result_area(self):
        self.result_frame = tk.Frame(self.root, bg="#eef5ff")
        self.result_frame.pack(padx=20, pady=10, fill=tk.BOTH, expand=True)

        # 当前天气卡片
        self.current_card = tk.LabelFrame(self.result_frame, text="  📍 当前天气  ",
                                           font=("微软雅黑", 11, "bold"),
                                           bg="#fffbeb", fg="#d97706", padx=15, pady=12)
        self.current_card.pack(fill=tk.X, pady=(0, 8))
        self.current_label = tk.Label(self.current_card, text="输入城市后点击查询",
                                       font=("微软雅黑", 11), bg="#fffbeb", fg="#666",
                                       justify="left", wraplength=420)
        self.current_label.pack(anchor="w")

        # 未来预报卡片
        self.forecast_card = tk.LabelFrame(self.result_frame, text="  📅 未来 3 天预报  ",
                                            font=("微软雅黑", 11, "bold"),
                                            bg="#ecfdf5", fg="#059669", padx=15, pady=12)
        self.forecast_card.pack(fill=tk.X, pady=(0, 8))
        self.forecast_label = tk.Label(self.forecast_card, text="查询后在此显示预报",
                                        font=("微软雅黑", 11), bg="#ecfdf5", fg="#666",
                                        justify="left", wraplength=420)
        self.forecast_label.pack(anchor="w")

    # ---------- 底部提示 ----------
    def _build_footer(self):
        tk.Label(self.root, text="💡 数据来源: wttr.in（免费开放）  |  按 Enter 可快捷查询",
                 font=("微软雅黑", 9), fg="#999", bg="#eef5ff").pack(side="bottom", pady=5)

    # ---------- 查询逻辑 ----------
    def do_query(self):
        city = self.city_var.get().strip()
        if not city:
            messagebox.showwarning("提示", "请输入城市名称！")
            return

        # 显示加载状态
        self.current_label.config(text="⏳ 正在查询，请稍候...", fg="#999")
        self.forecast_label.config(text="", fg="#999")
        self.root.update()

        try:
            data = query_weather(city)
        except requests.exceptions.ConnectionError:
            messagebox.showerror("网络错误", "无法连接天气服务器，请检查网络连接！")
            self.current_label.config(text="❌ 网络错误，请重试", fg="#dc2626")
            return
        except requests.exceptions.HTTPError:
            messagebox.showerror("查询失败", f"找不到城市「{city}」，请检查名称是否正确！")
            self.current_label.config(text="❌ 城市未找到，请重试", fg="#dc2626")
            return
        except Exception as e:
            messagebox.showerror("未知错误", f"查询出错：{e}")
            self.current_label.config(text="❌ 查询出错，请重试", fg="#dc2626")
            return

        # ---- 填充当前天气 ----
        c = data["current"]
        icon = get_icon(c["desc"])
        current_text = (
            f"{icon}  {c['city']}  ·  {c['desc']}\n"
            f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"
            f"🌡️ 温度：{c['temp']}°C（体感 {c['feels_like']}°C）\n"
            f"💧 湿度：{c['humidity']}%\n"
            f"🌬️ 风速：{c['wind_speed']} km/h（{c['wind_dir']}）\n"
            f"👁️ 能见度：{c['visibility']} km\n"
            f"☀️ 紫外线指数：{c['uv_index']}"
        )
        self.current_label.config(text=current_text, fg="#333")

        # ---- 填充未来预报 ----
        lines = []
        for i, f in enumerate(data["forecast"]):
            ficon = get_icon(f["desc"])
            lines.append(
                f"{ficon}  {f['date']}    {f['desc']}\n"
                f"      最高 {f['max_temp']}°C / 最低 {f['min_temp']}°C"
                f"      🌅 {f['sunrise']}  🌇 {f['sunset']}"
            )
        forecast_text = "\n\n".join(lines)
        self.forecast_label.config(text=forecast_text, fg="#333")


# ======================== 启动 ========================
if __name__ == "__main__":
    root = tk.Tk()
    app = WeatherApp(root)
    root.mainloop()