import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from tkinter.scrolledtext import ScrolledText
from xianbao.core.Task import TaskManager
from xianbao.service.rpa_backfilling_recong import Handler
import threading
import croniter
import datetime
import json


class ReconciliationTab(ttk.Frame):
    """
    对账回填功能的主界面类
    
    Args:
        parent: 父窗口组件
        db_path: 数据库文件路径
    """
    def __init__(self, parent, db_path):
        super().__init__(parent)
        self.db_path = db_path
        self.task_manager = TaskManager(db_path)
        self.is_running = False
        self.create_widgets()
    
    def create_widgets(self):
        """创建对账回填界面组件"""
        # 第一行：Cron表达式
        ttk.Label(self, text="Cron表达式:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
        self.cron_entry = ttk.Entry(self, width=30)
        self.cron_entry.grid(row=0, column=1, padx=5, pady=5, sticky="we")
        self.cron_entry.insert(0, "0 9 * * *")
        
        # 第二行：对账文件选择
        ttk.Button(self, text="选择对账文件", command=lambda: self.select_file("对账文件")).grid(row=1, column=0, padx=5, pady=5)
        self.recon_file_label = ttk.Label(self, text="未选择文件")
        self.recon_file_label.grid(row=1, column=1, padx=5, pady=5, sticky="w")
        
        # 第三行：流水文件选择
        ttk.Button(self, text="选择流水文件", command=lambda: self.select_file("流水文件")).grid(row=2, column=0, padx=5, pady=5)
        self.trans_file_label = ttk.Label(self, text="未选择文件")
        self.trans_file_label.grid(row=2, column=1, padx=5, pady=5, sticky="w")
        
        # 第四行：同步按钮
        self.sync_btn = ttk.Button(self, text="开始对账", command=self.start_reconciliation)
        self.sync_btn.grid(row=3, column=0, columnspan=2, padx=5, pady=5, sticky="we")
        
        # 第五行：状态标签
        self.status_label = ttk.Label(self, text="状态: 空闲")
        self.status_label.grid(row=4, column=0, columnspan=2, padx=5, pady=5, sticky="w")
        
        # 第六行：日志框
        self.log_text = ScrolledText(self, height=15, state="disabled")
        self.log_text.grid(row=5, column=0, columnspan=2, padx=5, pady=5, sticky="nsew")
        
        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(5, weight=1)
    
    def select_file(self, file_type):
        """选择对账或流水文件"""
        file_path = filedialog.askopenfilename(
            filetypes=[("Excel文件", ".xlsx .xlsm")]
        )
        if file_path:
            if file_type == "对账文件":
                self.recon_file_label.config(text=file_path)
            else:
                self.trans_file_label.config(text=file_path)
    
    def start_reconciliation(self):
        """启动对账任务"""
        if self.is_running:
            return
            
        # 验证Cron表达式
        cron_expr = self.cron_entry.get()
        try:
            croniter.croniter(cron_expr)
        except Exception as e:
            messagebox.showerror("错误", f"无效的Cron表达式: {e}")
            return
            
        # 验证文件路径
        recon_path = self.recon_file_label.cget("text")
        trans_path = self.trans_file_label.cget("text")
        if not recon_path or recon_path == "未选择文件" or not trans_path or trans_path == "未选择文件":
            messagebox.showerror("错误", "请先选择对账文件和流水文件")
            return
        
        # 更新状态
        self.is_running = True
        self.status_label.config(text="状态: 运行中")
        self.sync_btn.config(state="disabled")
        self.log_text.config(state="normal")
        self.log_text.delete(1.0, tk.END)  # 清空日志
        self.log_text.config(state="disabled")
        
        # 启动后台线程
        thread = threading.Thread(
            target=self.run_reconciliation, 
            args=(recon_path, trans_path)
        )
        thread.daemon = True
        thread.start()
    
    def run_reconciliation(self, recon_path, trans_path):
        """执行对账任务"""
        handler = Handler(recon_path, trans_path)
        page = 1
        per_page = 1000
        
        while True:
            tasks = self.rpa_backfilling(page, per_page)
            if not tasks:
                break
                
            for task in tasks:
                try:
                    handler.doh(task)
                    self.update_log(f"处理任务 {task['id']} 成功")
                except Exception as e:
                    self.update_log(f"处理任务 {task['id']} 失败: {str(e)}")
            
            page += 1
        
        handler._writer.close()
        
        # 恢复界面状态
        self.is_running = False
        self.status_label.config(text="状态: 空闲")
        self.sync_btn.config(state="normal")
        self.update_log("所有对账任务处理完成")
    
    def rpa_backfilling(self, page=1, per_page=1000):
        """分页获取任务列表"""
        offset = (page - 1) * per_page
        sql = f"""
            SELECT * FROM tasks 
            ORDER BY created_time DESC 
            LIMIT {per_page} OFFSET {offset}
        """
        tasks = self.task_manager.execute_custom_sql(sql)

        # 反序列化meta字段
        for task in tasks:
            if 'meta' in task and task['meta']:
                task['meta'] = json.loads(task['meta'])

        return tasks
    
    def update_log(self, message):
        """更新日志"""
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_message = f"[{timestamp}] {message}\n"
        
        self.log_text.config(state="normal")
        self.log_text.insert("end", log_message)
        self.log_text.see("end")
        self.log_text.config(state="disabled")