import re
import tkinter as tk
from tkinter import messagebox


PALETTE = {
    "bg": "#f4efe7",
    "panel": "#fffaf3",
    "hero": "#16324f",
    "hero_muted": "#d5e5f7",
    "border": "#d8cfc1",
    "text": "#1f2a36",
    "muted": "#66717e",
    "accent": "#e67e22",
    "accent_dark": "#bf6313",
    "accent_soft": "#fff1df",
    "success": "#1f8a70",
    "success_soft": "#e7f6f2",
    "alert": "#b85042",
}

PRICING_RULES = [
    ("1 - 10 页", "0.5 元 / 页", "最低 1 元"),
    ("11 - 50 页", "0.4 元 / 页", "最低 5 元"),
    ("51 - 100 页", "0.35 元 / 页", "按页计算"),
    ("101 - 500 页", "0.25 元 / 页", "按页计算"),
    ("501 页以上", "0.2 元 / 页", "按页计算"),
]

RULE_COLUMNS = 2
INFO_COLUMNS = 3
DEFAULT_WINDOW_WIDTH = 1020
DEFAULT_WINDOW_HEIGHT = 720
MIN_WINDOW_WIDTH = 940
MIN_WINDOW_HEIGHT = 660


def parse_input(text):
    normalized_text = re.sub(r"(\d+(?:\.\d+)?)\s+(元|圆)", r"\1\2", text.strip())
    tokens = [item for item in re.split(r"[+,\s，、]+", normalized_text) if item]
    if not tokens:
        raise ValueError("请输入页数或彩印/A3金额，例如 3元+8+10")

    pages = []
    fixed_amounts = []
    preview_tokens = []

    for token in tokens:
        amount_match = re.fullmatch(r"(\d+(?:\.\d+)?)(元|圆)", token)
        if amount_match:
            value = float(amount_match.group(1))
            if value <= 0:
                raise ValueError("彩印/A3金额必须大于 0")
            fixed_amounts.append(value)
            preview_tokens.append(f"{amount_match.group(1)}元")
            continue

        if token.isdigit():
            value = int(token)
            if value <= 0:
                raise ValueError("页数必须大于 0")
            pages.append(value)
            preview_tokens.append(str(value))
            continue

        raise ValueError("输入格式有误：页数请填正整数，彩印/A3金额请写成 3元、5.5圆，可用 +、逗号或空格分隔")

    return {
        "pages": pages,
        "fixed_amounts": fixed_amounts,
        "preview_tokens": preview_tokens,
    }


def custom_round(price):
    integer = int(price)
    decimal = round(price - integer, 2)
    if decimal < 0.2:
        return float(integer)
    if decimal <= 0.7:
        return integer + 0.5
    return float(integer + 1)


def fmt_price(value):
    return str(int(value)) if float(value).is_integer() else f"{value:.1f}"


def calculate_price(total_pages):
    if 1 <= total_pages <= 10:
        unit_price = 0.5
        raw_price = total_pages * unit_price
        final_before_round = max(raw_price, 1.0)
        note = "已按 1 元最低消费计算" if raw_price < 1 else "按基础单价计算"
        tier = "小批量"
    elif 11 <= total_pages <= 50:
        unit_price = 0.4
        raw_price = total_pages * unit_price
        final_before_round = max(raw_price, 5.0)
        note = "已按 5 元最低消费计算" if raw_price < 5 else "按基础单价计算"
        tier = "常规批量"
    elif 51 <= total_pages <= 100:
        unit_price = 0.35
        raw_price = total_pages * unit_price
        final_before_round = raw_price
        note = "按基础单价计算"
        tier = "进阶批量"
    elif 101 <= total_pages <= 500:
        unit_price = 0.25
        raw_price = total_pages * unit_price
        final_before_round = raw_price
        note = "按基础单价计算"
        tier = "大批量"
    else:
        unit_price = 0.2
        raw_price = total_pages * unit_price
        final_before_round = raw_price
        note = "按基础单价计算"
        tier = "超大批量"

    final_price = custom_round(final_before_round)
    return {
        "unit_price": unit_price,
        "raw_price": raw_price,
        "final_price": final_price,
        "note": note,
        "tier": tier,
    }


class PrintPricingApp:
    def __init__(self, root):
        self.root = root
        self.root.title("网络天下电脑打印价格计算器")
        self.root.configure(bg=PALETTE["bg"])

        self.input_var = tk.StringVar()
        self.status_var = tk.StringVar(value="输入页数或彩印/A3金额后点击“立即计算”，支持 3元+8+10、5.5元, 12, 15 这种格式。")
        self.file_count_var = tk.StringVar(value="0 份文件")
        self.total_pages_var = tk.StringVar(value="0 页")
        self.input_preview_var = tk.StringVar(value="等待输入")
        self.tier_var = tk.StringVar(value="未计算")
        self.unit_price_var = tk.StringVar(value="0 元 / 页")
        self.raw_price_var = tk.StringVar(value="0 元")
        self.rounding_var = tk.StringVar(value="按规则取整")
        self.note_var = tk.StringVar(value="暂无说明")
        self.final_price_var = tk.StringVar(value="0 元")

        self.latest_summary = ""

        self.build_ui()
        self.auto_fit_window()
        self.root.bind("<Return>", lambda event: self.calculate())

    def auto_fit_window(self):
        self.root.update_idletasks()

        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        max_width = screen_width - 72 if screen_width > 72 else screen_width
        max_height = screen_height - 72 if screen_height > 72 else screen_height

        if max_width < MIN_WINDOW_WIDTH or max_height < MIN_WINDOW_HEIGHT:
            self.root.state("zoomed")
            return

        width = min(DEFAULT_WINDOW_WIDTH, max_width)
        height = min(DEFAULT_WINDOW_HEIGHT, max_height)

        x = max((screen_width - width) // 2, 0)
        y = max((screen_height - height) // 2, 0)

        self.root.geometry(f"{width}x{height}+{x}+{y}")
        self.root.minsize(min(MIN_WINDOW_WIDTH, max_width), min(MIN_WINDOW_HEIGHT, max_height))

    def build_ui(self):
        outer = tk.Frame(self.root, bg=PALETTE["bg"])
        outer.pack(fill="both", expand=True, padx=18, pady=16)

        self.build_hero(outer)

        content = tk.Frame(outer, bg=PALETTE["bg"])
        content.pack(fill="both", expand=True, pady=(12, 0))
        content.grid_columnconfigure(0, weight=11)
        content.grid_columnconfigure(1, weight=10)
        content.grid_rowconfigure(0, weight=1)

        left = tk.Frame(content, bg=PALETTE["panel"], highlightbackground=PALETTE["border"], highlightthickness=1)
        left.grid(row=0, column=0, sticky="nsew", padx=(0, 8))

        right = tk.Frame(content, bg=PALETTE["panel"], highlightbackground=PALETTE["border"], highlightthickness=1)
        right.grid(row=0, column=1, sticky="nsew", padx=(8, 0))

        self.build_input_panel(left)
        self.build_result_panel(right)

    def build_hero(self, parent):
        hero = tk.Frame(parent, bg=PALETTE["hero"], height=110)
        hero.pack(fill="x")
        hero.pack_propagate(False)

        stripe = tk.Frame(hero, bg=PALETTE["accent"], height=4)
        stripe.pack(fill="x", side="top")

        top = tk.Frame(hero, bg=PALETTE["hero"])
        top.pack(fill="both", expand=True, padx=22, pady=16)
        top.grid_columnconfigure(0, weight=1)

        text_block = tk.Frame(top, bg=PALETTE["hero"])
        text_block.grid(row=0, column=0, sticky="w")

        tk.Label(
            text_block,
            text="网络天下电脑打印价格计算器",
            bg=PALETTE["hero"],
            fg="white",
            font=("Microsoft YaHei UI", 18, "bold"),
        ).pack(anchor="w")

        tk.Label(
            text_block,
            text="把命令行脚本升级成更清晰、更体面的报价界面，适合直接给同学或客户使用。",
            bg=PALETTE["hero"],
            fg=PALETTE["hero_muted"],
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="w", pady=(6, 0))

        badge = tk.Frame(top, bg=PALETTE["accent_soft"], padx=12, pady=8)
        badge.grid(row=0, column=1, sticky="e")

        tk.Label(
            badge,
            text="规则自动取整",
            bg=PALETTE["accent_soft"],
            fg=PALETTE["accent_dark"],
            font=("Bahnschrift", 9, "bold"),
        ).pack(anchor="e")

        tk.Label(
            badge,
            text="支持多文件合计、结果复制",
            bg=PALETTE["accent_soft"],
            fg=PALETTE["accent_dark"],
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="e", pady=(2, 0))

    def build_input_panel(self, parent):
        body = tk.Frame(parent, bg=PALETTE["panel"])
        body.pack(fill="both", expand=True, padx=18, pady=16)

        tk.Label(
            body,
            text="输入内容",
            bg=PALETTE["panel"],
            fg=PALETTE["text"],
            font=("Microsoft YaHei UI", 15, "bold"),
        ).pack(anchor="w")

        tk.Label(
            body,
            text="支持页数和彩印/A3金额混合输入，可用 +、逗号、空格分隔。",
            bg=PALETTE["panel"],
            fg=PALETTE["muted"],
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="w", pady=(4, 12))

        input_card = tk.Frame(body, bg="white", highlightbackground=PALETTE["border"], highlightthickness=1)
        input_card.pack(fill="x")
        input_card.bind("<Button-3>", self.paste_into_entry)

        self.entry = tk.Entry(
            input_card,
            textvariable=self.input_var,
            relief="flat",
            bd=0,
            bg="white",
            fg=PALETTE["text"],
            insertbackground=PALETTE["text"],
            font=("Bahnschrift", 16),
        )
        self.entry.pack(fill="x", padx=14, pady=12)
        self.entry.bind("<Button-3>", self.paste_into_entry)
        self.entry.focus_set()

        tk.Label(
            body,
            text="示例：3元+8+10    或    5.5元, 12, 15    或    10圆+20",
            bg=PALETTE["panel"],
            fg=PALETTE["muted"],
            font=("Bahnschrift", 9),
        ).pack(anchor="w", pady=(8, 14))

        button_row = tk.Frame(body, bg=PALETTE["panel"])
        button_row.pack(fill="x")

        self.make_button(button_row, "立即计算", PALETTE["accent"], "white", self.calculate).pack(side="left")
        self.make_button(button_row, "重新复制", PALETTE["success"], "white", self.copy_result).pack(side="left", padx=8)
        self.make_button(button_row, "清空重填", "#e9dfd2", PALETTE["text"], self.reset).pack(side="left")

        status_frame = tk.Frame(body, bg=PALETTE["accent_soft"], padx=10, pady=8)
        status_frame.pack(fill="x", pady=(16, 14))

        tk.Label(
            status_frame,
            textvariable=self.status_var,
            bg=PALETTE["accent_soft"],
            fg=PALETTE["accent_dark"],
            justify="left",
            wraplength=290,
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="w")

        tk.Label(
            body,
            text="计价规则",
            bg=PALETTE["panel"],
            fg=PALETTE["text"],
            font=("Microsoft YaHei UI", 14, "bold"),
        ).pack(anchor="w", pady=(4, 10))

        rules_panel = tk.Frame(body, bg=PALETTE["panel"])
        rules_panel.pack(fill="x")

        for column in range(RULE_COLUMNS):
            rules_panel.grid_columnconfigure(column, weight=1)

        for idx, (page_range, price, note) in enumerate(PRICING_RULES, start=1):
            row = (idx - 1) // RULE_COLUMNS
            column = (idx - 1) % RULE_COLUMNS
            self.make_rule_tile(rules_panel, idx, page_range, price, note, row, column)

    def build_result_panel(self, parent):
        body = tk.Frame(parent, bg=PALETTE["panel"])
        body.pack(fill="both", expand=True, padx=18, pady=16)

        tk.Label(
            body,
            text="计算结果",
            bg=PALETTE["panel"],
            fg=PALETTE["text"],
            font=("Microsoft YaHei UI", 15, "bold"),
        ).pack(anchor="w")

        tk.Label(
            body,
            text="右侧会展示汇总页数、计价档位、原始金额和最终报价。",
            bg=PALETTE["panel"],
            fg=PALETTE["muted"],
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="w", pady=(4, 12))

        total_card = tk.Frame(body, bg=PALETTE["hero"], padx=16, pady=14)
        total_card.pack(fill="x")

        tk.Label(
            total_card,
            text="最终应付总价",
            bg=PALETTE["hero"],
            fg=PALETTE["hero_muted"],
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="w")

        tk.Label(
            total_card,
            textvariable=self.final_price_var,
            bg=PALETTE["hero"],
            fg="white",
            font=("Bahnschrift", 24, "bold"),
        ).pack(anchor="w", pady=(8, 0))

        info_grid = tk.Frame(body, bg=PALETTE["panel"])
        info_grid.pack(fill="both", expand=True, pady=(12, 0))
        for column in range(INFO_COLUMNS):
            info_grid.grid_columnconfigure(column, weight=1)

        info_items = [
            ("输入预览", self.input_preview_var),
            ("文件数量", self.file_count_var),
            ("总页数", self.total_pages_var),
            ("计价档位", self.tier_var),
            ("适用单价", self.unit_price_var),
            ("原始金额", self.raw_price_var),
            ("取整结果", self.rounding_var),
            ("备注说明", self.note_var),
        ]

        for idx, (title, variable) in enumerate(info_items):
            row = idx // INFO_COLUMNS
            column = idx % INFO_COLUMNS
            self.make_info_tile(info_grid, title, variable, row, column)

        footer = tk.Frame(body, bg=PALETTE["success_soft"], padx=12, pady=10)
        footer.pack(fill="x", pady=(14, 0))

        tk.Label(
            footer,
            text="取整规则：小数低于 0.2 直接舍去，0.2 到 0.7 记为 0.5，高于 0.7 进 1。",
            bg=PALETTE["success_soft"],
            fg=PALETTE["success"],
            wraplength=300,
            justify="left",
            font=("Microsoft YaHei UI", 9),
        ).pack(anchor="w")

    def make_rule_tile(self, parent, idx, page_range, price, note, row, column):
        card = tk.Frame(
            parent,
            bg=PALETTE["bg"],
            highlightbackground=PALETTE["border"],
            highlightthickness=1,
            padx=10,
            pady=8,
        )
        card.grid(row=row, column=column, sticky="nsew", padx=4, pady=4)

        tk.Label(
            card,
            text=f"{idx:02d}",
            bg=PALETTE["accent_soft"],
            fg=PALETTE["accent_dark"],
            font=("Bahnschrift", 8, "bold"),
            padx=6,
            pady=2,
        ).pack(anchor="w")

        tk.Label(
            card,
            text=page_range,
            bg=PALETTE["bg"],
            fg=PALETTE["text"],
            font=("Microsoft YaHei UI", 9, "bold"),
            justify="left",
            wraplength=180,
        ).pack(anchor="w", pady=(8, 0))

        tk.Label(
            card,
            text=price,
            bg=PALETTE["bg"],
            fg=PALETTE["accent_dark"],
            font=("Bahnschrift", 10, "bold"),
        ).pack(anchor="w", pady=(8, 2))

        tk.Label(
            card,
            text=note,
            bg=PALETTE["bg"],
            fg=PALETTE["muted"],
            font=("Microsoft YaHei UI", 7),
            justify="left",
            wraplength=180,
        ).pack(anchor="w")

    def make_info_tile(self, parent, title, variable, row, column):
        tile = tk.Frame(parent, bg=PALETTE["bg"], padx=12, pady=12)
        tile.grid(row=row, column=column, sticky="nsew", padx=4, pady=4)

        tk.Label(
            tile,
            text=title,
            bg=PALETTE["bg"],
            fg=PALETTE["muted"],
            font=("Microsoft YaHei UI", 8),
        ).pack(anchor="w")

        tk.Label(
            tile,
            textvariable=variable,
            bg=PALETTE["bg"],
            fg=PALETTE["text"],
            wraplength=180,
            justify="left",
            font=("Microsoft YaHei UI", 10, "bold"),
        ).pack(anchor="w", fill="x", pady=(6, 0))

    def make_button(self, parent, text, bg, fg, command):
        button = tk.Button(
            parent,
            text=text,
            command=command,
            relief="flat",
            bd=0,
            padx=14,
            pady=8,
            bg=bg,
            fg=fg,
            activebackground=bg if bg == "#e9dfd2" else self.darken(bg),
            activeforeground=fg,
            cursor="hand2",
            font=("Microsoft YaHei UI", 9, "bold"),
        )
        return button

    def darken(self, color):
        color = color.lstrip("#")
        rgb = [max(0, int(color[i:i + 2], 16) - 18) for i in (0, 2, 4)]
        return "#{:02x}{:02x}{:02x}".format(*rgb)

    def paste_into_entry(self, event=None):
        try:
            clipboard_text = self.root.clipboard_get()
        except tk.TclError:
            self.status_var.set("剪贴板里没有可粘贴的内容。")
            return "break"

        clipboard_text = re.sub(r"[\r\n\t]+", " ", clipboard_text).strip()
        if not clipboard_text:
            self.status_var.set("剪贴板里没有可粘贴的内容。")
            return "break"

        self.entry.focus_set()
        self.input_var.set(clipboard_text)
        self.entry.icursor(tk.END)
        self.calculate()
        return "break"

    def calculate(self):
        user_input = self.input_var.get()

        try:
            parsed_input = parse_input(user_input)
        except ValueError as exc:
            self.status_var.set(str(exc))
            self.input_preview_var.set("输入无效")
            self.file_count_var.set("0 份文件")
            self.total_pages_var.set("0 页")
            self.tier_var.set("未计算")
            self.unit_price_var.set("0 元 / 页")
            self.raw_price_var.set("0 元")
            self.rounding_var.set("按规则取整")
            self.note_var.set("输入有误")
            self.final_price_var.set("0 元")
            self.latest_summary = ""
            return

        pages = parsed_input["pages"]
        fixed_amounts = parsed_input["fixed_amounts"]
        total_pages = sum(pages)
        file_count = len(parsed_input["preview_tokens"])
        fixed_total = sum(fixed_amounts)

        if total_pages > 0:
            result = calculate_price(total_pages)
            page_final_price = result["final_price"]
            tier_text = result["tier"]
            unit_price_text = f"{result['unit_price']} 元 / 页"
            raw_price_text = f"{total_pages} × {result['unit_price']} = {result['raw_price']:.2f} 元"
            rounding_text = f"{fmt_price(page_final_price)} 元"
            note_text = result["note"]
        else:
            result = None
            page_final_price = 0.0
            tier_text = "彩印/A3"
            unit_price_text = "按金额直加"
            raw_price_text = "无页数计价"
            rounding_text = "无需取整"
            note_text = "彩印/A3金额直接计入总价"

        if fixed_total > 0:
            fixed_text = f"{fmt_price(fixed_total)} 元"
            if total_pages > 0:
                tier_text = f"{tier_text} + 彩印/A3"
                raw_price_text = f"{raw_price_text}；彩印/A3 {fixed_text}"
                rounding_text = f"页数部分取整后 {fmt_price(page_final_price)} 元"
                note_text = f"{note_text}，另加彩印/A3 {fixed_text}"
            else:
                raw_price_text = f"彩印/A3合计 {fixed_text}"

        final_total = page_final_price + fixed_total
        preview = " + ".join(parsed_input["preview_tokens"])
        final_price = fmt_price(final_total)

        self.input_preview_var.set(preview)
        self.file_count_var.set(f"{file_count} 份文件")
        self.total_pages_var.set(f"{total_pages} 页")
        self.tier_var.set(tier_text)
        self.unit_price_var.set(unit_price_text)
        self.raw_price_var.set(raw_price_text)
        self.rounding_var.set(rounding_text)
        self.note_var.set(note_text)
        self.final_price_var.set(f"{final_price} 元")
        self.status_var.set("计算完成，可以直接复制报价内容发给对方。")

        summary_lines = [f"文件数量：{file_count} 份"]
        if total_pages > 0:
            summary_lines.append(f"总打印页数：{total_pages} 页")
            summary_lines.append(f"页数部分价格：{fmt_price(page_final_price)} 元")
        if fixed_total > 0:
            summary_lines.append(f"彩印/A3合计：{fmt_price(fixed_total)} 元")
        summary_lines.append("")
        summary_lines.append(f"最终应付总价：{final_price} 元")
        self.latest_summary = "\n".join(summary_lines)
        if self.copy_result(show_prompt=False):
            self.status_var.set("计算完成，报价内容已自动复制到剪贴板。")
        else:
            self.status_var.set("计算完成，但自动复制失败，请点击“重新复制”。")

    def copy_result(self, show_prompt=True):
        if not self.latest_summary:
            if show_prompt:
                messagebox.showinfo("提示", "请先完成一次计算，再复制报价。")
            return False

        try:
            self.root.clipboard_clear()
            self.root.clipboard_append(self.latest_summary)
            self.root.update()
        except tk.TclError:
            if show_prompt:
                messagebox.showerror("提示", "复制失败，请稍后再试。")
            return False

        if show_prompt:
            self.status_var.set("报价内容已复制到剪贴板。")
        return True

    def reset(self):
        self.input_var.set("")
        self.status_var.set("输入页数或彩印/A3金额后点击“立即计算”，支持 3元+8+10、5.5元, 12, 15 这种格式。")
        self.file_count_var.set("0 份文件")
        self.total_pages_var.set("0 页")
        self.input_preview_var.set("等待输入")
        self.tier_var.set("未计算")
        self.unit_price_var.set("0 元 / 页")
        self.raw_price_var.set("0 元")
        self.rounding_var.set("按规则取整")
        self.note_var.set("暂无说明")
        self.final_price_var.set("0 元")
        self.latest_summary = ""
        self.entry.focus_set()


def main():
    root = tk.Tk()
    PrintPricingApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
