import tkinter as tk
from tkinter import ttk, messagebox
import urllib.request
import json
import os
import threading
from datetime import datetime

CACHE_FILE = "exchange_rates.json"
BASE_CURRENCY = "USD"  # 基准货币

class CurrencyConverter:
    def __init__(self, root):
        self.root = root
        self.root.title("026. 货币单位转换器")
        self.root.geometry("480x340")
        self.root.resizable(False, False)

        self.rates = {}
        self.last_update = None
        self.online = False

        self.currencies = [
            "USD", "EUR", "JPY", "GBP", "CNY",
            "CAD", "AUD", "CHF", "HKD", "KRW",
            "SGD", "INR", "RUB", "BRL", "NZD"
        ]

        self.load_cache()
        self.build_ui()
        self.fetch_rates()

    # ========== UI 构建 ==========
    def build_ui(self):
        # 标题
        tk.Label(
            self.root, text="💰 货币单位转换器",
            font=("微软雅黑", 16, "bold")
        ).pack(pady=10)

        # 金额输入
        input_frame = tk.Frame(self.root)
        input_frame.pack(pady=5)

        tk.Label(input_frame, text="金额：").pack(side=tk.LEFT)
        self.amount_entry = tk.Entry(input_frame, width=15, font=("Consolas", 12))
        self.amount_entry.pack(side=tk.LEFT, padx=5)
        self.amount_entry.insert(0, "100")

        # 货币选择
        select_frame = tk.Frame(self.root)
        select_frame.pack(pady=10)

        # 源货币
        tk.Label(select_frame, text="从：").grid(row=0, column=0, padx=5)
        self.from_currency = ttk.Combobox(
            select_frame, values=self.currencies, width=8, state="readonly"
        )
        self.from_currency.grid(row=0, column=1, padx=5)
        self.from_currency.set("USD")

        # 交换按钮
        swap_btn = tk.Button(
            select_frame, text="⇄", font=("Arial", 14),
            width=3, command=self.swap_currencies
        )
        swap_btn.grid(row=0, column=2, padx=10)

        # 目标货币
        tk.Label(select_frame, text="到：").grid(row=0, column=3, padx=5)
        self.to_currency = ttk.Combobox(
            select_frame, values=self.currencies, width=8, state="readonly"
        )
        self.to_currency.grid(row=0, column=4, padx=5)
        self.to_currency.set("CNY")

        # 转换按钮
        convert_btn = tk.Button(
            self.root, text="转 换",
            width=15, height=2,
            bg="#4CAF50", fg="white",
            font=("微软雅黑", 11, "bold"),
            command=self.convert
        )
        convert_btn.pack(pady=10)

        # 结果显示
        self.result_label = tk.Label(
            self.root, text="等待转换...",
            font=("Consolas", 14), fg="#1565C0"
        )
        self.result_label.pack(pady=5)

        # 状态栏
        self.status_label = tk.Label(
            self.root, text="初始化中...",
            font=("微软雅黑", 9), fg="#666"
        )
        self.status_label.pack(pady=5)

        # 绑定回车键
        self.root.bind("<Return>", lambda e: self.convert())

    # ========== 汇率获取 ==========
    def fetch_rates(self):
        """在线获取汇率（使用 exchangerate-api.com 免费接口）"""
        def task():
            try:
                url = f"https://open.er-api.com/v6/latest/{BASE_CURRENCY}"
                req = urllib.request.Request(url)
                req.add_header("User-Agent", "Mozilla/5.0")

                with urllib.request.urlopen(req, timeout=8) as response:
                    data = json.loads(response.read().decode("utf-8"))

                if data["result"] == "success":
                    self.rates = data["rates"]
                    self.last_update = data["time_last_update_utc"]
                    self.online = True
                    self.save_cache()
                    self.root.after(0, self.update_status)
                else:
                    self.root.after(0, self.use_cache)

            except Exception:
                self.root.after(0, self.use_cache)

        threading.Thread(target=task, daemon=True).start()

    # ========== 缓存管理 ==========
    def load_cache(self):
        if os.path.exists(CACHE_FILE):
            try:
                with open(CACHE_FILE, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    self.rates = data.get("rates", {})
                    self.last_update = data.get("last_update", "未知")
            except:
                self.rates = {}

    def save_cache(self):
        data = {
            "rates": self.rates,
            "last_update": self.last_update
        }
        with open(CACHE_FILE, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

    def use_cache(self):
        self.online = False
        self.update_status()
        if not self.rates:
            messagebox.showwarning(
                "网络错误",
                "无法连接网络，且无本地缓存数据！\n请检查网络连接后重试。"
            )

    def update_status(self):
        if self.online:
            status = f"✅ 在线模式 | 更新时间：{self.last_update}"
            self.status_label.config(text=status, fg="#2E7D32")
        else:
            status = f"⚠️ 离线模式 | 最后更新：{self.last_update}"
            self.status_label.config(text=status, fg="#F57C00")

    # ========== 核心逻辑 ==========
    def convert(self):
        try:
            amount = float(self.amount_entry.get().strip())
        except ValueError:
            messagebox.showwarning("输入错误", "请输入有效的数字金额！")
            return

        from_cur = self.from_currency.get()
        to_cur = self.to_currency.get()

        if not self.rates:
            messagebox.showwarning("数据缺失", "汇率数据尚未加载完成，请稍候！")
            return

        if from_cur not in self.rates or to_cur not in self.rates:
            messagebox.showwarning("不支持", f"不支持 {from_cur} 或 {to_cur} 的转换！")
            return

        # 转换公式：amount × (to_rate / from_rate)
        from_rate = self.rates[from_cur]
        to_rate = self.rates[to_cur]

        result = amount * (to_rate / from_rate)
        result = round(result, 2)

        self.result_label.config(
            text=f"{amount} {from_cur} = {result} {to_cur}"
        )

    def swap_currencies(self):
        """交换源货币和目标货币"""
        from_cur = self.from_currency.get()
        to_cur = self.to_currency.get()
        self.from_currency.set(to_cur)
        self.to_currency.set(from_cur)
        self.convert()


if __name__ == "__main__":
    root = tk.Tk()
    CurrencyConverter(root)
    root.mainloop()