import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import datetime
import json
import os
from collections import defaultdict

# ========== 记账本核心类 ==========
class TravelLedger:
    def __init__(self, trip_name="我的旅行"):
        self.trip_name = trip_name
        self.records = []  # 每一条记录：{date, category, amount, note}
        self.categories = ["餐饮", "住宿", "交通", "购物", "门票", "其他"]
        self.data_file = f"{trip_name}_ledger.json"
        self.load_data()
    
    def add_record(self, date, category, amount, note=""):
        """添加一条记账记录"""
        try:
            amount = float(amount)
            if amount <= 0:
                raise ValueError("金额必须大于0")
            record = {
                "date": date,
                "category": category,
                "amount": amount,
                "note": note
            }
            self.records.append(record)
            self.save_data()
            return True, "✅ 记账成功！"
        except ValueError as e:
            return False, f"❌ 金额格式错误：{str(e)}"
    
    def delete_record(self, index):
        """删除指定索引的记录"""
        if 0 <= index < len(self.records):
            deleted = self.records.pop(index)
            self.save_data()
            return True, f"✅ 已删除：{deleted['category']} {deleted['amount']}元"
        return False, "❌ 记录不存在"
    
    def get_summary(self):
        """获取汇总统计"""
        if not self.records:
            return "📊 暂无记账记录"
        
        total = sum(r["amount"] for r in self.records)
        by_category = defaultdict(float)
        for r in self.records:
            by_category[r["category"]] += r["amount"]
        
        summary = f"📊 总支出：{total:.2f} 元\n"
        summary += f"📝 共 {len(self.records)} 笔记录\n"
        summary += "\n📂 分类汇总：\n"
        for cat, amt in sorted(by_category.items(), key=lambda x: x[1], reverse=True):
            percentage = (amt / total * 100) if total > 0 else 0
            summary += f"  {cat}：{amt:.2f} 元 ({percentage:.1f}%)\n"
        return summary
    
    def get_daily_summary(self):
        """按日期汇总"""
        by_date = defaultdict(float)
        for r in self.records:
            by_date[r["date"]] += r["amount"]
        return dict(by_date)
    
    def save_data(self):
        """保存到JSON文件"""
        data = {
            "trip_name": self.trip_name,
            "records": self.records
        }
        with open(self.data_file, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
    
    def load_data(self):
        """从JSON文件加载"""
        if os.path.exists(self.data_file):
            try:
                with open(self.data_file, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    self.trip_name = data.get("trip_name", self.trip_name)
                    self.records = data.get("records", [])
            except:
                self.records = []

# ========== 图形界面 ==========
class LedgerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("📒 旅行记账本")
        self.root.geometry("800x700")
        self.root.resizable(True, True)
        
        # 初始化记账本
        self.ledger = TravelLedger("我的旅行")
        
        # 设置样式
        style = ttk.Style()
        style.theme_use('clam')
        
        # ---------- 主框架 ----------
        main_frame = ttk.Frame(root, padding="15")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title = ttk.Label(main_frame, text="📒 旅行记账本", font=('Arial', 18, 'bold'))
        title.pack(pady=5)
        
        # ---------- 输入区域 ----------
        input_frame = ttk.LabelFrame(main_frame, text="✏️ 记一笔", padding="15")
        input_frame.pack(fill=tk.X, pady=10)
        
        # 日期
        ttk.Label(input_frame, text="日期:").grid(row=0, column=0, sticky=tk.W, pady=5)
        self.date_entry = ttk.Entry(input_frame, width=15)
        self.date_entry.grid(row=0, column=1, pady=5, padx=5)
        self.date_entry.insert(0, datetime.datetime.now().strftime("%Y-%m-%d"))
        
        # 分类
        ttk.Label(input_frame, text="分类:").grid(row=0, column=2, sticky=tk.W, pady=5, padx=(20,0))
        self.category_var = tk.StringVar()
        self.category_combo = ttk.Combobox(input_frame, textvariable=self.category_var, 
                                           values=self.ledger.categories, width=12)
        self.category_combo.grid(row=0, column=3, pady=5, padx=5)
        self.category_combo.current(0)
        
        # 金额
        ttk.Label(input_frame, text="金额(元):").grid(row=0, column=4, sticky=tk.W, pady=5, padx=(20,0))
        self.amount_entry = ttk.Entry(input_frame, width=12)
        self.amount_entry.grid(row=0, column=5, pady=5, padx=5)
        
        # 备注
        ttk.Label(input_frame, text="备注:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.note_entry = ttk.Entry(input_frame, width=50)
        self.note_entry.grid(row=1, column=1, columnspan=5, pady=5, padx=5, sticky=tk.W)
        
        # 按钮行
        btn_frame = ttk.Frame(input_frame)
        btn_frame.grid(row=2, column=0, columnspan=6, pady=10)
        
        self.add_btn = ttk.Button(btn_frame, text="💾 添加记录", command=self.add_record)
        self.add_btn.pack(side=tk.LEFT, padx=5)
        
        self.delete_btn = ttk.Button(btn_frame, text="🗑️ 删除选中", command=self.delete_record)
        self.delete_btn.pack(side=tk.LEFT, padx=5)
        
        self.refresh_btn = ttk.Button(btn_frame, text="🔄 刷新", command=self.refresh_all)
        self.refresh_btn.pack(side=tk.LEFT, padx=5)
        
        # ---------- 统计信息 ----------
        stats_frame = ttk.LabelFrame(main_frame, text="📊 统计", padding="10")
        stats_frame.pack(fill=tk.X, pady=10)
        
        self.stats_text = tk.Text(stats_frame, height=6, wrap=tk.WORD, font=('Consolas', 10))
        self.stats_text.pack(fill=tk.BOTH, expand=True)
        self.stats_text.config(state=tk.DISABLED)
        
        # ---------- 记录列表 ----------
        list_frame = ttk.LabelFrame(main_frame, text="📋 记账明细", padding="10")
        list_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        
        # 表格
        columns = ("#", "日期", "分类", "金额", "备注")
        self.tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=10)
        
        # 设置列
        self.tree.heading("#", text="序号")
        self.tree.heading("日期", text="日期")
        self.tree.heading("分类", text="分类")
        self.tree.heading("金额", text="金额(元)")
        self.tree.heading("备注", text="备注")
        
        self.tree.column("#", width=50, anchor=tk.CENTER)
        self.tree.column("日期", width=100, anchor=tk.CENTER)
        self.tree.column("分类", width=100, anchor=tk.CENTER)
        self.tree.column("金额", width=100, anchor=tk.E)
        self.tree.column("备注", width=300, anchor=tk.W)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定双击事件（可编辑备注）
        self.tree.bind("<Double-1>", self.edit_note)
        
        # ---------- 底部操作栏 ----------
        bottom_frame = ttk.Frame(main_frame)
        bottom_frame.pack(fill=tk.X, pady=10)
        
        self.export_btn = ttk.Button(bottom_frame, text="📤 导出为TXT", command=self.export_txt)
        self.export_btn.pack(side=tk.LEFT, padx=5)
        
        self.clear_btn = ttk.Button(bottom_frame, text="⚠️ 清空所有记录", command=self.clear_all)
        self.clear_btn.pack(side=tk.LEFT, padx=5)
        
        self.status_label = ttk.Label(bottom_frame, text="💡 就绪", foreground="gray")
        self.status_label.pack(side=tk.RIGHT, padx=10)
        
        # 加载初始数据
        self.refresh_all()
    
    # ---------- 核心功能 ----------
    def add_record(self):
        """添加记录"""
        date = self.date_entry.get().strip()
        category = self.category_var.get()
        amount = self.amount_entry.get().strip()
        note = self.note_entry.get().strip()
        
        if not date or not amount:
            messagebox.showwarning("提示", "请填写日期和金额")
            return
        
        success, msg = self.ledger.add_record(date, category, amount, note)
        if success:
            self.status_label.config(text=msg, foreground="green")
            self.amount_entry.delete(0, tk.END)
            self.note_entry.delete(0, tk.END)
            self.refresh_all()
        else:
            messagebox.showerror("错误", msg)
    
    def delete_record(self):
        """删除选中记录"""
        selected = self.tree.selection()
        if not selected:
            messagebox.showwarning("提示", "请先选择要删除的记录")
            return
        
        if messagebox.askyesno("确认删除", "确定要删除选中的记录吗？"):
            # 获取选中项的索引
            for item in selected:
                values = self.tree.item(item, "values")
                # 找到对应的记录索引
                for idx, record in enumerate(self.ledger.records):
                    if (record["date"] == values[1] and 
                        record["category"] == values[2] and 
                        float(record["amount"]) == float(values[3]) and
                        record["note"] == values[4]):
                        self.ledger.delete_record(idx)
                        break
            self.refresh_all()
            self.status_label.config(text="✅ 已删除选中记录", foreground="green")
    
    def refresh_all(self):
        """刷新显示"""
        # 刷新表格
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        for idx, record in enumerate(self.ledger.records, 1):
            self.tree.insert("", tk.END, values=(
                idx,
                record["date"],
                record["category"],
                f"{record['amount']:.2f}",
                record["note"]
            ))
        
        # 刷新统计
        self.stats_text.config(state=tk.NORMAL)
        self.stats_text.delete(1.0, tk.END)
        self.stats_text.insert(tk.END, self.ledger.get_summary())
        self.stats_text.config(state=tk.DISABLED)
        
        # 更新状态
        self.status_label.config(text=f"📊 共 {len(self.ledger.records)} 条记录", foreground="gray")
    
    def edit_note(self, event):
        """双击编辑备注"""
        selected = self.tree.selection()
        if not selected:
            return
        
        item = selected[0]
        values = self.tree.item(item, "values")
        idx = int(values[0]) - 1
        
        if 0 <= idx < len(self.ledger.records):
            # 弹出编辑窗口
            edit_window = tk.Toplevel(self.root)
            edit_window.title("编辑备注")
            edit_window.geometry("400x150")
            edit_window.resizable(False, False)
            
            ttk.Label(edit_window, text=f"编辑第 {idx+1} 条记录的备注").pack(pady=10)
            
            note_var = tk.StringVar(value=self.ledger.records[idx]["note"])
            note_entry = ttk.Entry(edit_window, textvariable=note_var, width=50)
            note_entry.pack(pady=10, padx=20)
            
            def save_note():
                self.ledger.records[idx]["note"] = note_var.get()
                self.ledger.save_data()
                self.refresh_all()
                edit_window.destroy()
                self.status_label.config(text="✅ 备注已更新", foreground="green")
            
            ttk.Button(edit_window, text="💾 保存", command=save_note).pack(pady=10)
    
    def export_txt(self):
        """导出为TXT文件"""
        if not self.ledger.records:
            messagebox.showinfo("提示", "没有记录可导出")
            return
        
        filename = f"{self.ledger.trip_name}_账单_{datetime.datetime.now().strftime('%Y%m%d')}.txt"
        try:
            with open(filename, "w", encoding="utf-8") as f:
                f.write("="*50 + "\n")
                f.write(f"📒 {self.ledger.trip_name} 账单\n")
                f.write(f"📅 导出时间：{datetime.datetime.now().strftime('%Y-%m-%d %H:%M')}\n")
                f.write("="*50 + "\n\n")
                
                total = 0
                for idx, record in enumerate(self.ledger.records, 1):
                    line = f"{idx:3d}. {record['date']}  {record['category']:6s}  {record['amount']:8.2f}  {record['note']}"
                    f.write(line + "\n")
                    total += record["amount"]
                
                f.write("\n" + "-"*50 + "\n")
                f.write(f"📊 合计：{total:.2f} 元\n")
                f.write(f"📝 共 {len(self.ledger.records)} 笔记录\n")
            
            messagebox.showinfo("导出成功", f"账单已导出到：{filename}")
            self.status_label.config(text=f"✅ 已导出：{filename}", foreground="green")
        except Exception as e:
            messagebox.showerror("导出失败", f"导出时出错：{str(e)}")
    
    def clear_all(self):
        """清空所有记录"""
        if not self.ledger.records:
            messagebox.showinfo("提示", "没有记录可清空")
            return
        
        if messagebox.askyesno("⚠️ 危险操作", "确定要清空所有记账记录吗？此操作不可恢复！"):
            self.ledger.records = []
            self.ledger.save_data()
            self.refresh_all()
            self.status_label.config(text="🗑️ 已清空所有记录", foreground="red")

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