import csv
import io
import threading
import tkinter as tk
import urllib.request
from datetime import datetime
from tkinter import ttk

URL = "https://rate.bot.com.tw/xrt/flcsv/0/day"
TARGETS = [
    ("USD", "美元"),
    ("JPY", "日幣"),
    ("EUR", "歐元"),
]


def fetch_rates():
    req = urllib.request.Request(URL, headers={"User-Agent": "Mozilla/5.0"})
    with urllib.request.urlopen(req, timeout=10) as resp:
        raw = resp.read().decode("utf-8-sig", errors="replace")
    reader = csv.reader(io.StringIO(raw))
    next(reader, None)
    rates = {}
    wanted = {code for code, _ in TARGETS}
    for row in reader:
        if not row:
            continue
        code = row[0].strip()
        if code in wanted:
            rates[code] = float(row[13])
    return rates


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("台灣銀行 即期賣出匯率")
        self.geometry("360x320")
        self.configure(bg="#f5f6fa")
        self.resizable(False, False)

        style = ttk.Style(self)
        try:
            style.theme_use("vista")
        except tk.TclError:
            style.theme_use("clam")

        style.configure("TFrame", background="#f5f6fa")
        style.configure("Title.TLabel",
                        background="#f5f6fa",
                        foreground="#1f2937",
                        font=("Microsoft JhengHei UI", 14, "bold"))
        style.configure("Name.TLabel",
                        background="#ffffff",
                        foreground="#374151",
                        font=("Microsoft JhengHei UI", 12))
        style.configure("Rate.TLabel",
                        background="#ffffff",
                        foreground="#0f766e",
                        font=("Consolas", 14, "bold"))
        style.configure("Hint.TLabel",
                        background="#f5f6fa",
                        foreground="#6b7280",
                        font=("Microsoft JhengHei UI", 9))
        style.configure("Accent.TButton",
                        font=("Microsoft JhengHei UI", 10, "bold"),
                        padding=6)

        container = ttk.Frame(self, padding=(18, 16))
        container.pack(fill="both", expand=True)

        ttk.Label(container, text="台灣銀行 即期賣出", style="Title.TLabel").pack(anchor="w")
        ttk.Label(container, text="資料來源：rate.bot.com.tw",
                  style="Hint.TLabel").pack(anchor="w", pady=(2, 12))

        card = tk.Frame(container, bg="#ffffff", highlightthickness=1,
                        highlightbackground="#e5e7eb")
        card.pack(fill="x")

        self.rate_labels = {}
        for i, (code, name) in enumerate(TARGETS):
            row = tk.Frame(card, bg="#ffffff")
            row.pack(fill="x", padx=14, pady=10)
            ttk.Label(row, text=f"{name}  {code}", style="Name.TLabel").pack(side="left")
            lbl = ttk.Label(row, text="--", style="Rate.TLabel")
            lbl.pack(side="right")
            self.rate_labels[code] = lbl
            if i < len(TARGETS) - 1:
                tk.Frame(card, bg="#f1f2f6", height=1).pack(fill="x", padx=10)

        bottom = ttk.Frame(container)
        bottom.pack(fill="x", pady=(14, 0))

        self.status = ttk.Label(bottom, text="載入中…", style="Hint.TLabel")
        self.status.pack(side="left")

        self.btn = ttk.Button(bottom, text="重新整理", style="Accent.TButton",
                              command=self.refresh)
        self.btn.pack(side="right")

        self.after(100, self.refresh)

    def refresh(self):
        self.btn.state(["disabled"])
        self.status.configure(text="載入中…", foreground="#6b7280")
        threading.Thread(target=self._worker, daemon=True).start()

    def _worker(self):
        try:
            rates = fetch_rates()
            self.after(0, self._on_success, rates)
        except Exception as e:
            self.after(0, self._on_error, e)

    def _on_success(self, rates):
        for code, _ in TARGETS:
            value = rates.get(code)
            text = f"{value:.4f}" if value is not None else "查無資料"
            self.rate_labels[code].configure(text=text)
        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.status.configure(text=f"更新時間：{now}", foreground="#6b7280")
        self.btn.state(["!disabled"])

    def _on_error(self, err):
        self.status.configure(text=f"載入失敗：{err}", foreground="#b91c1c")
        self.btn.state(["!disabled"])


if __name__ == "__main__":
    App().mainloop()
