#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""主窗口模块"""

import os
import sys
import subprocess
import tkinter as tk
from tkinter import messagebox, filedialog, scrolledtext

from app.config.settings import ConfigManager
from app.core.utils.log_utils import set_log_level

from .theme import THEMES, get_theme_mode, set_theme_mode, create_modern_button, create_card_frame
from .logging_ui import add_to_log, poll_log_queue
from .ui_widgets import StatusBar, ToolTip
from .user_settings import (
    load_user_settings, save_user_settings, refresh_recent_list_widget,
    _extract_path_from_recent_item, clear_recent_files, RECENT_LIST_WIDGET,
)
from .file_operations import (
    ensure_directories, open_result_directory, clean_cache,
    clean_data_files, clean_result_files,
)
from .action_handlers import (
    process_single_image_with_status, run_pipeline_directly,
    batch_ocr_with_status, batch_process_orders_with_status,
    merge_orders_with_status, process_excel_file_with_status,
    process_dropped_file, batch_process_all_inputs,
)
from .memory_editor import show_memory_editor
from .config_dialog import show_config_dialog
from .barcode_editor import edit_barcode_mappings
from .shortcuts import bind_keyboard_shortcuts
from app.core.utils.dialog_utils import show_cloud_sync_dialog
from .db_viewer import show_db_viewer


def _init_window():
    """初始化窗口、主题和设置，返回 (root, theme, settings, dnd_supported)"""
    ensure_directories()

    dnd_supported = False
    try:
        from tkinterdnd2 import TkinterDnD, DND_FILES
        root = TkinterDnD.Tk()
        dnd_supported = True
    except Exception:
        root = tk.Tk()

    settings = load_user_settings()
    theme_mode = settings.get('theme_mode', get_theme_mode())
    set_theme_mode(theme_mode)

    try:
        cfg_for_title = ConfigManager()
        ver = cfg_for_title.get('App', 'version', fallback='dev')
        root.title(f"益选-OCR订单处理系统 v{ver} by 欢欢欢")
    except Exception:
        root.title("益选-OCR订单处理系统 by 欢欢欢")

    root.geometry("900x600")
    settings['window_size'] = "900x600"
    theme = THEMES[get_theme_mode()]
    root.configure(bg=theme["bg"])

    try:
        log_level = settings.get('log_level')
        if log_level:
            set_log_level(log_level)
        concurrency = settings.get('concurrency_max_workers')
        if concurrency:
            cfg = ConfigManager()
            cfg.update('Performance', 'max_workers', str(concurrency))
            cfg.save_config()
    except Exception:
        pass

    try:
        root.iconbitmap(default="")
    except Exception:
        pass

    return root, theme, settings, dnd_supported


def _create_left_panel(content_frame, theme, log_text, status_bar):
    """创建左侧面板：完整流程、OCR处理、Excel处理、最近文件"""
    left_panel = create_card_frame(content_frame)
    left_panel.pack(side=tk.LEFT, fill=tk.BOTH, expand=False, padx=(0, 5), pady=5)
    left_panel.configure(width=160)

    panel_content = tk.Frame(left_panel, bg=theme["card_bg"])
    panel_content.pack(fill=tk.BOTH, expand=True, padx=10, pady=(5, 10))

    # 完整流程区
    pipeline_section = tk.LabelFrame(
        panel_content, text="完整流程", bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    pipeline_section.pack(fill=tk.X, pady=(0, 8))
    pipeline_frame = tk.Frame(pipeline_section, bg=theme["card_bg"])
    pipeline_frame.pack(fill=tk.X, padx=8, pady=6)
    
    btn_onekey = create_modern_button(pipeline_frame, "一键处理", lambda: run_pipeline_directly(log_text, status_bar), "primary", px_width=150, px_height=32)
    btn_onekey.pack(anchor='w', pady=3)
    ToolTip(btn_onekey.winfo_children()[0], "选择图片或Excel，自动完成OCR识别和采购单生成全流程")
    
    btn_batch = create_modern_button(pipeline_frame, "批量处理", lambda: batch_process_all_inputs(log_text, status_bar), "primary", px_width=150, px_height=32)
    btn_batch.pack(anchor='w', pady=3)
    ToolTip(btn_batch.winfo_children()[0], "扫描 data/input 文件夹，处理所有未识别的图片")

    # OCR处理区
    core_section = tk.LabelFrame(
        panel_content, text="OCR处理", bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    core_section.pack(fill=tk.X, pady=(0, 8))
    core_buttons_frame = tk.Frame(core_section, bg=theme["card_bg"])
    core_buttons_frame.pack(fill=tk.X, padx=8, pady=6)
    core_row1 = tk.Frame(core_buttons_frame, bg=theme["card_bg"])
    core_row1.pack(fill=tk.X, pady=3)
    create_modern_button(core_row1, "批量识别", lambda: batch_ocr_with_status(log_text, status_bar), "primary", px_width=72, px_height=32).pack(side=tk.LEFT, padx=(0, 3))
    create_modern_button(core_row1, "单个识别", lambda: process_single_image_with_status(log_text, status_bar), "primary", px_width=72, px_height=32).pack(side=tk.LEFT, padx=(3, 0))

    # Excel处理区
    ocr_section = tk.LabelFrame(
        panel_content, text="Excel处理", bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    ocr_section.pack(fill=tk.X, pady=(0, 8))
    ocr_buttons_frame = tk.Frame(ocr_section, bg=theme["card_bg"])
    ocr_buttons_frame.pack(fill=tk.X, padx=8, pady=6)
    ocr_row1 = tk.Frame(ocr_buttons_frame, bg=theme["card_bg"])
    ocr_row1.pack(fill=tk.X, pady=3)
    create_modern_button(ocr_row1, "批量处理", lambda: batch_process_orders_with_status(log_text, status_bar), "primary", px_width=72, px_height=32).pack(side=tk.LEFT, padx=(0, 3))
    create_modern_button(ocr_row1, "单个处理", lambda: process_excel_file_with_status(log_text, status_bar), "primary", px_width=72, px_height=32).pack(side=tk.LEFT, padx=(3, 0))

    # 最近文件区
    _create_recent_files_section(panel_content, theme, log_text)


def _create_recent_files_section(parent, theme, log_text):
    """创建最近文件列表区域"""
    recent_section = tk.LabelFrame(
        parent, text="最近文件", bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    recent_section.pack(fill=tk.BOTH, pady=(0, 12))
    recent_frame = tk.Frame(recent_section, bg=theme["card_bg"])
    recent_frame.pack(fill=tk.BOTH, padx=8, pady=6)
    recent_top = tk.Frame(recent_frame, bg=theme["card_bg"])
    recent_top.pack(fill=tk.X)

    def _resize_recent_top(e):
        try:
            h = max(int(e.height * 0.85), 180)
            recent_top.configure(height=h)
        except Exception:
            pass

    try:
        recent_top.pack_propagate(False)
    except Exception:
        pass
    recent_frame.bind('<Configure>', _resize_recent_top)

    recent_rect = tk.Frame(recent_top, bg=theme["card_bg"], highlightbackground=theme["border"], highlightthickness=1)
    recent_rect.pack(fill=tk.BOTH, expand=True)
    recent_list = tk.Listbox(recent_rect, height=20)
    recent_scrollbar = tk.Scrollbar(recent_rect)
    recent_list.configure(yscrollcommand=recent_scrollbar.set)
    recent_scrollbar.configure(command=recent_list.yview)
    recent_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    recent_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

    import app.ui.user_settings as _us_mod
    _us_mod.RECENT_LIST_WIDGET = recent_list

    def _open_selected_event(evt=None):
        try:
            idxs = recent_list.curselection()
            if not idxs:
                return
            p = _extract_path_from_recent_item(recent_list.get(idxs[0]))
            if os.path.exists(p):
                os.startfile(p)
            else:
                messagebox.showwarning("文件不存在", p)
        except Exception as e:
            messagebox.showerror("打开失败", str(e))

    recent_list.bind('<Double-Button-1>', _open_selected_event)
    refresh_recent_list_widget()
    rf_btns = tk.Frame(recent_frame, bg=theme["card_bg"])
    rf_btns.pack(fill=tk.X, pady=6)

    def clear_list():
        clear_recent_files()
        recent_list.delete(0, tk.END)

    create_modern_button(rf_btns, "清空列表", clear_list, "primary", px_width=72, px_height=32).pack(side=tk.LEFT, padx=(3, 0))

    def purge_invalid():
        try:
            kept = []
            for i in range(recent_list.size()):
                item = recent_list.get(i)
                p = _extract_path_from_recent_item(item)
                if os.path.exists(p):
                    kept.append(p)
            try:
                kept_sorted = sorted(kept, key=lambda p: os.path.getmtime(p), reverse=True)
            except Exception:
                kept_sorted = kept
            s = load_user_settings()
            s['recent_files'] = kept_sorted
            save_user_settings(s)
            recent_list.delete(0, tk.END)
            for i, p in enumerate(s['recent_files'][:recent_list.size() or len(s['recent_files'])], start=1):
                recent_list.insert(tk.END, f"{i}. {p}")
            refresh_recent_list_widget()
            add_to_log(log_text, "已清理无效的最近文件条目\n", "success")
        except Exception as e:
            messagebox.showerror("清理失败", str(e))

    create_modern_button(rf_btns, "清理无效", purge_invalid, "primary", px_width=72, px_height=32).pack(side=tk.LEFT, padx=(3, 0))


def _create_right_panel(content_frame, theme, log_text, root, status_bar, config):
    """创建右侧面板：快捷操作、系统设置"""
    right_panel = create_card_frame(content_frame)
    right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=False, padx=(5, 0), pady=5)
    right_panel.configure(width=380)

    right_panel_content = tk.Frame(right_panel, bg=theme["card_bg"])
    right_panel_content.pack(fill=tk.BOTH, expand=True, padx=10, pady=(5, 10))

    # 工具功能区
    tools_section = tk.LabelFrame(
        right_panel_content, text="快捷操作", bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    tools_section.pack(fill=tk.X, pady=(0, 8))
    tools_buttons_frame = tk.Frame(tools_section, bg=theme["card_bg"])
    tools_buttons_frame.pack(fill=tk.X, padx=8, pady=6)
    tk.Frame(tools_buttons_frame, bg=theme["card_bg"]).pack(fill=tk.X, pady=3)

    create_modern_button(tools_buttons_frame, "打开结果目录", lambda: open_result_directory(), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "打开输出目录", lambda: os.startfile(config.get_path('Paths', 'output_folder', fallback='data/output', create=True)), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "打开输入目录", lambda: os.startfile(config.get_path('Paths', 'input_folder', fallback='data/input', create=True)), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "合并订单", lambda: merge_orders_with_status(log_text, status_bar), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "数据库内容", lambda: show_db_viewer(root, config=config), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "清除缓存", lambda: clean_cache(log_text), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "清理input/out文件", lambda: clean_data_files(log_text), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(tools_buttons_frame, "清理结果文件", lambda: clean_result_files(log_text), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)

    # 系统设置区
    settings_section = tk.LabelFrame(
        right_panel_content, text="系统设置", bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    settings_section.pack(fill=tk.X, pady=(0, 8))
    settings_buttons_frame = tk.Frame(settings_section, bg=theme["card_bg"])
    settings_buttons_frame.pack(fill=tk.X, padx=8, pady=6)
    create_modern_button(settings_buttons_frame, "系统设置", lambda: show_config_dialog(root, config), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(settings_buttons_frame, "条码映射", lambda: edit_barcode_mappings(log_text), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(settings_buttons_frame, "云端同步", lambda: show_cloud_sync_dialog(root), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)
    create_modern_button(settings_buttons_frame, "商品记忆库", lambda: show_memory_editor(root), "primary", px_width=132, px_height=32).pack(anchor='w', pady=3)


def _setup_drag_area(mid_container, theme, dnd_supported, log_text, status_bar):
    """创建拖拽/点击选择文件区域"""
    drag_panel = create_card_frame(mid_container)
    drag_panel.pack(side=tk.TOP, fill=tk.X, padx=(5, 5), pady=(0, 5))
    drag_panel_content = tk.Frame(drag_panel, bg=theme["card_bg"])
    drag_panel_content.pack(fill=tk.X, padx=10, pady=6)

    dnd_section = tk.LabelFrame(
        drag_panel_content, bg=theme["card_bg"], fg=theme["fg"],
        font=("Microsoft YaHei UI", 10, "bold"), relief="flat", borderwidth=0
    )
    dnd_section.pack(fill=tk.X, pady=(0, 0))
    dnd_frame = tk.Frame(dnd_section, bg=theme["card_bg"], highlightthickness=1, highlightbackground=theme["border"])
    dnd_frame.configure(height=60)
    dnd_frame.pack(fill=tk.X, padx=8, pady=6)
    try:
        dnd_frame.pack_propagate(False)
    except Exception:
        pass

    def _set_highlight(active: bool):
        try:
            dnd_frame.configure(highlightbackground=theme["info"] if active else theme["border"])
        except Exception:
            pass

    dnd_frame.bind('<Enter>', lambda e: _set_highlight(True))
    dnd_frame.bind('<Leave>', lambda e: _set_highlight(False))

    msg_row = tk.Frame(dnd_frame, bg=theme["card_bg"])
    msg_row.pack(fill=tk.X)
    if dnd_supported:
        tk.Label(
            msg_row, text="拖拽已启用：拖拽或点击此区域选择文件",
            bg=theme["card_bg"], fg="#999999", justify="center"
        ).pack(fill=tk.X)
    else:
        tk.Label(
            msg_row, text="点击此区域选择文件；可安装拖拽支持",
            bg=theme["card_bg"], fg="#999999", justify="center"
        ).pack(fill=tk.X)

    if not dnd_supported:
        btn_row = tk.Frame(dnd_frame, bg=theme["card_bg"])
        btn_row.pack(fill=tk.X)

        is_frozen = getattr(sys, 'frozen', False)

        def copy_install():
            try:
                mid_container.winfo_toplevel().clipboard_clear()
                mid_container.winfo_toplevel().clipboard_append("pip install tkinterdnd2")
                messagebox.showinfo("已复制", "已复制安装命令：pip install tkinterdnd2")
            except Exception as e:
                messagebox.showwarning("复制失败", str(e))

        if is_frozen:
            tk.Label(
                btn_row, text="EXE版不支持运行时安装，请用源码版安装后重新打包",
                bg=theme["card_bg"], fg="#999999", font=("Microsoft YaHei UI", 8)
            ).pack(side=tk.RIGHT, padx=4)
        else:
            def install_and_restart():
                try:
                    add_to_log(log_text, "开始安装拖拽支持库 tkinterdnd2...\n", "info")
                    cmd = [sys.executable, "-m", "pip", "install", "tkinterdnd2"]
                    result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
                    add_to_log(log_text, result.stdout + "\n", "info")
                    add_to_log(log_text, "安装成功，准备重启程序以启用拖拽...\n", "success")
                    if messagebox.askyesno("安装完成", "已安装拖拽支持，是否立即重启应用？"):
                        os.execl(sys.executable, sys.executable, *sys.argv)
                except subprocess.CalledProcessError as e:
                    add_to_log(log_text, f"安装失败: {e.stderr}\n", "error")
                    messagebox.showerror("安装失败", f"安装输出:\n{e.stderr}")
                except Exception as e:
                    add_to_log(log_text, f"安装失败: {str(e)}\n", "error")
                    messagebox.showerror("安装失败", str(e))

            create_modern_button(btn_row, "一键安装拖拽", install_and_restart, "primary", px_width=132, px_height=28).pack(side=tk.RIGHT, padx=(3, 0))

        create_modern_button(btn_row, "复制安装命令", copy_install, "primary", px_width=132, px_height=28).pack(side=tk.RIGHT)

    # 点击拖拽框选择文件
    def _click_select(evt=None):
        try:
            files = filedialog.askopenfilenames(
                title="选择图片或Excel文件",
                filetypes=[
                    ("支持文件", "*.xlsx *.xls *.jpg *.jpeg *.png *.bmp"),
                    ("Excel", "*.xlsx *.xls"),
                    ("图片", "*.jpg *.jpeg *.png *.bmp"),
                    ("所有文件", "*.*"),
                ]
            )
            if not files:
                return
            for p in files:
                process_dropped_file(log_text, status_bar, p)
        except Exception as e:
            messagebox.showerror("选择失败", str(e))

    dnd_frame.bind('<Button-1>', _click_select)
    msg_row.bind('<Button-1>', _click_select)

    if dnd_supported:
        def _on_drop(event):
            try:
                data = event.data
                paths = []
                buf = ""
                in_brace = False
                for ch in data:
                    if ch == '{':
                        in_brace = True
                        buf = ""
                    elif ch == '}':
                        in_brace = False
                        paths.append(buf)
                        buf = ""
                    elif ch == ' ' and not in_brace:
                        if buf:
                            paths.append(buf)
                            buf = ""
                    else:
                        buf += ch
                if buf:
                    paths.append(buf)
                for p in paths:
                    process_dropped_file(log_text, status_bar, p)
            except Exception as e:
                add_to_log(log_text, f"拖拽处理失败: {str(e)}\n", "error")

        try:
            from tkinterdnd2 import DND_FILES
            dnd_frame.drop_target_register(DND_FILES)
            dnd_frame.dnd_bind('<<Drop>>', _on_drop)
        except Exception:
            pass


def _create_log_panel(mid_container, theme):
    """创建中间日志面板，返回 log_text widget"""
    log_panel = create_card_frame(mid_container, "处理日志")
    log_panel.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=(5, 5), pady=5)

    log_text = scrolledtext.ScrolledText(
        log_panel, wrap=tk.WORD, width=68, height=26,
        bg=theme["log_bg"], fg=theme["log_fg"],
        font=("Consolas", 9), state=tk.DISABLED,
        relief="flat", borderwidth=0
    )
    log_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=(5, 10))

    log_text.tag_configure("command", foreground=theme["info"], font=("Consolas", 9, "bold"))
    log_text.tag_configure("time", foreground=theme["secondary_bg"], font=("Consolas", 8))
    log_text.tag_configure("separator", foreground=theme["border"])
    log_text.tag_configure("success", foreground=theme["success"], font=("Consolas", 9, "bold"))
    log_text.tag_configure("error", foreground=theme["error"], font=("Consolas", 9, "bold"))
    log_text.tag_configure("warning", foreground=theme["warning"], font=("Consolas", 9, "bold"))
    log_text.tag_configure("info", foreground=theme["info"], font=("Consolas", 9))

    poll_log_queue(log_text)

    try:
        _ver = ConfigManager().get('App', 'version', fallback='')
        _ver_str = f" v{_ver}" if _ver else ""
    except Exception:
        _ver_str = ""
    add_to_log(log_text, f"欢迎使用 益选-OCR订单处理系统{_ver_str}\n", "success")
    add_to_log(log_text, "系统已就绪，请选择相应功能进行操作。\n\n", "info")
    add_to_log(log_text, "功能说明：\n", "command")
    add_to_log(log_text, "• 完整处理流程：一键完成OCR识别和Excel处理\n", "info")
    add_to_log(log_text, "• 批量处理订单：批量处理多个订单文件\n", "info")
    add_to_log(log_text, "• 处理烟草订单：专门处理烟草类订单\n", "info")
    add_to_log(log_text, "• 合并订单：将多个订单合并为一个文件\n\n", "info")
    cfg = ConfigManager()
    add_to_log(log_text, f"请将需要处理的图片文件放入 {cfg.get_path('Paths', 'input_folder', fallback='data/input')} 目录中。\n", "warning")
    add_to_log(log_text, f"OCR识别结果保存在 {cfg.get_path('Paths', 'output_folder', fallback='data/output')} 目录，处理完成的订单保存在 {cfg.get_path('Paths', 'result_folder', fallback='data/result')} 目录中。\n\n", "warning")
    add_to_log(log_text, "=" * 50 + "\n\n", "separator")

    return log_text


def main():
    """主函数"""
    try:
        root, theme, settings, dnd_supported = _init_window()
        config = ConfigManager()

        # 主容器
        main_container = tk.Frame(root, bg=theme["bg"])
        main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        content_frame = tk.Frame(main_container, bg=theme["bg"])
        content_frame.pack(fill=tk.BOTH, expand=True)

        # 中间容器（拖拽区 + 日志区）
        mid_container = tk.Frame(content_frame, bg=theme["bg"])
        mid_container.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(5, 5), pady=5)

        log_text = _create_log_panel(mid_container, theme)

        # 状态栏
        status_bar = StatusBar(root)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        # 左侧面板
        _create_left_panel(content_frame, theme, log_text, status_bar)

        # 右侧面板
        _create_right_panel(content_frame, theme, log_text, root, status_bar, config)

        # 拖拽区域
        _setup_drag_area(mid_container, theme, dnd_supported, log_text, status_bar)

        # 快捷键 + 关闭事件
        def on_close():
            try:
                w = root.winfo_width()
                h = root.winfo_height()
                settings['window_size'] = f"{w}x{h}"
                settings['theme_mode'] = get_theme_mode()
                save_user_settings(settings)
            except Exception:
                pass
            root.destroy()

        root.protocol("WM_DELETE_WINDOW", on_close)
        bind_keyboard_shortcuts(root, log_text, status_bar)

        root.mainloop()

    except Exception as e:
        import traceback
        error_msg = f"程序启动失败: {str(e)}\n详细错误信息:\n{traceback.format_exc()}"
        print(error_msg)
        try:
            import tkinter.messagebox as mb
            mb.showerror("启动错误", f"程序启动失败:\n{str(e)}")
        except Exception:
            pass
