from __future__ import annotations

import tkinter as tk
from tkinter import ttk, messagebox
import math
from fractions import Fraction


# ───────────────────────── 核心算法 ─────────────────────────

def simplify_fraction(num: int, den: int):
    """
    化简分数
    返回: (简分子, 简分母, 最大公约数, 是否整数)
    """
    if den == 0:
        return (0, 0, 0, False)
    
    sign = -1 if (num < 0) ^ (den < 0) else 1
    num = abs(num)
    den = abs(den)
    
    g = math.gcd(num, den)
    if g == 0:
        return (0, 0, 0, False)
    
    sn = sign * (num // g)
    sd = den // g
    
    return (sn, sd, g, sn % sd == 0)


def to_mixed(fr: Fraction):
    """假分数转带分数字符串"""
    if fr.denominator == 1:
        return str(fr.numerator)
    whole = fr.numerator // fr.denominator
    rem = abs(fr.numerator) % fr.denominator
    if whole == 0:
        return f"{fr.numerator}/{fr.denominator}"
    return f"{whole} {rem}/{fr.denominator}"


# ───────────────────────── GUI ─────────────────────────

class FractionApp:
    def __init__(self, root: tk.Tk):
        self.root = root
        root.title("📐 分数化简 / 约分工具")
        root.geometry("640x560")

        notebook = ttk.Notebook(root)
        notebook.pack(fill="both", expand=True, padx=10, pady=10)

        # 页1：单个化简
        f1 = ttk.Frame(notebook)
        notebook.add(f1, text="单个化简")
        self._build_single(f1)

        # 页2：小数↔分数
        f2 = ttk.Frame(notebook)
        notebook.add(f2, text="小数⇄分数")
        self._build_decimal(f2)

        # 页3：分数运算
        f3 = ttk.Frame(notebook)
        notebook.add(f3, text="分数运算")
        self._build_op(f3)

    # ---------- 页1 ----------
    def _build_single(self, parent):
        tk.Label(parent, text="分子").grid(row=0, column=0, padx=5, pady=5)
        self.num_var = tk.StringVar(value="12")
        tk.Entry(parent, textvariable=self.num_var, width=10).grid(row=0, column=1)

        tk.Label(parent, text="分母").grid(row=1, column=0, padx=5, pady=5)
        self.den_var = tk.StringVar(value="18")
        tk.Entry(parent, textvariable=self.den_var, width=10).grid(row=1, column=1)

        tk.Button(parent, text="化简", command=self._do_simplify).grid(row=2, column=0, pady=8)
        tk.Button(parent, text="清空", command=lambda: (self.num_var.set(""), self.den_var.set(""), self.out1.set(""))).grid(row=2, column=1)

        self.out1 = tk.StringVar()
        tk.Label(parent, textvariable=self.out1, justify="left", fg="blue").grid(row=3, column=0, columnspan=4, sticky="w", padx=5, pady=5)

    def _do_simplify(self):
        try:
            n = int(self.num_var.get())
            d = int(self.den_var.get())
        except ValueError:
            self.out1.set("❌ 请输入整数")
            return

        if d == 0:
            self.out1.set("❌ 分母不能为 0")
            return

        sn, sd, g, is_int = simplify_fraction(n, d)
        fr = Fraction(sn, sd)
        lines = [
            f"原分数：{n}/{d}",
            f"GCD({abs(n)}, {abs(d)}) = {g}",
            f"化简：({n}÷{g}) / ({d}÷{g}) = {sn}/{sd}",
            f"带分数：{to_mixed(fr)}",
            f"小数：{float(fr):.6f}",
        ]
        self.out1.set("\n".join(lines))

    # ---------- 页2 ----------
    def _build_decimal(self, parent):
        tk.Label(parent, text="小数").grid(row=0, column=0, padx=5, pady=5)
        self.dec_var = tk.StringVar(value="0.75")
        tk.Entry(parent, textvariable=self.dec_var, width=12).grid(row=0, column=1)
        tk.Button(parent, text="转分数", command=self._dec_to_fr).grid(row=0, column=2)

        tk.Label(parent, text="分数(a/b)").grid(row=1, column=0, padx=5, pady=5)
        self.fr_var = tk.StringVar(value="3/8")
        tk.Entry(parent, textvariable=self.fr_var, width=12).grid(row=1, column=1)
        tk.Button(parent, text="转小数", command=self._fr_to_dec).grid(row=1, column=2)

        self.out2 = tk.StringVar()
        tk.Label(parent, textvariable=self.out2, justify="left", fg="blue").grid(row=3, column=0, columnspan=4, sticky="w", padx=5, pady=5)

    def _dec_to_fr(self):
        try:
            x = float(self.dec_var.get())
            fr = Fraction(x).limit_denominator(1000000)
            self.out2.set(f"{x} = {fr}  （带分数 {to_mixed(fr)}）")
        except ValueError:
            self.out2.set("❌ 小数格式错误")

    def _fr_to_dec(self):
        try:
            fr = Fraction(self.fr_var.get())
            self.out2.set(f"{fr} = {float(fr):.6f}")
        except ValueError:
            self.out2.set("❌ 分数格式应为 a/b")

    # ---------- 页3 ----------
    def _build_op(self, parent):
        tk.Label(parent, text="分数1").grid(row=0, column=0)
        self.f1_var = tk.StringVar(value="1/2")
        tk.Entry(parent, textvariable=self.f1_var, width=8).grid(row=0, column=1)

        self.op_var = tk.StringVar(value="+")
        ttk.Combobox(parent, textvariable=self.op_var, values=["+", "-", "*", "/"], width=4).grid(row=0, column=2)

        tk.Label(parent, text="分数2").grid(row=0, column=3)
        self.f2_var = tk.StringVar(value="1/3")
        tk.Entry(parent, textvariable=self.f2_var, width=8).grid(row=0, column=4)

        tk.Button(parent, text="计算", command=self._calc).grid(row=1, column=0, pady=8, columnspan=5)

        self.out3 = tk.StringVar()
        tk.Label(parent, textvariable=self.out3, justify="left", fg="blue").grid(row=2, column=0, columnspan=5, sticky="w", padx=5, pady=5)

    def _calc(self):
        try:
            a = Fraction(self.f1_var.get())
            b = Fraction(self.f2_var.get())
            op = self.op_var.get()
            if op == "+":
                r = a + b
            elif op == "-":
                r = a - b
            elif op == "*":
                r = a * b
            elif op == "/":
                r = a / b
            else:
                r = None
            self.out3.set(f"{a} {op} {b} = {r}\n带分数：{to_mixed(r)}\n小数：{float(r):.6f}")
        except ZeroDivisionError:
            self.out3.set("❌ 除数不能为 0")
        except ValueError:
            self.out3.set("❌ 分数格式错误，应为 a/b")


# ───────────────────────── 启动 ─────────────────────────

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