#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""命令执行器模块"""

import os
import sys
import time
import subprocess
import datetime
import re
import tkinter as tk
from tkinter import messagebox
from threading import Thread

from app.ui.logging_ui import LogRedirector
from app.ui.result_previews import show_result_preview

# 任务状态跟踪
_RUNNING_TASK = None


def get_running_task():
    return _RUNNING_TASK


def set_running_task(val):
    global _RUNNING_TASK
    _RUNNING_TASK = val


def run_command_with_logging(command, log_widget, status_bar=None, on_complete=None):
    """运行命令并将输出重定向到日志窗口"""
    if _RUNNING_TASK is not None:
        messagebox.showinfo("任务进行中", "请等待当前任务完成后再执行新的操作。")
        return

    def run_in_thread():
        global _RUNNING_TASK
        _RUNNING_TASK = command

        if status_bar:
            status_bar.set_running(True)

        start_time = datetime.datetime.now()
        start_perf = time.perf_counter()
        log_widget.configure(state=tk.NORMAL)
        log_widget.delete(1.0, tk.END)
        log_widget.insert(tk.END, f"执行命令: {' '.join(command)}\n", "command")
        log_widget.insert(tk.END, f"开始时间: {start_time.strftime('%Y-%m-%d %H:%M:%S')}\n", "time")
        log_widget.insert(tk.END, "=" * 50 + "\n\n", "separator")
        log_widget.configure(state=tk.DISABLED)

        old_stdout = sys.stdout
        old_stderr = sys.stderr

        log_redirector = LogRedirector(log_widget)

        env = os.environ.copy()
        try:
            from app.config.settings import ConfigManager
            cfg = ConfigManager()
            env["OCR_OUTPUT_DIR"] = cfg.get_path('Paths', 'output_folder', fallback='data/output', create=True)
            env["OCR_INPUT_DIR"] = cfg.get_path('Paths', 'input_folder', fallback='data/input', create=True)
            env["OCR_TEMP_DIR"] = cfg.get_path('Paths', 'temp_folder', fallback='data/temp', create=True)
        except Exception:
            # 回退：使用 exe/脚本所在目录
            app_root = os.path.dirname(sys.executable) if getattr(sys, 'frozen', False) else os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
            env["OCR_OUTPUT_DIR"] = os.path.join(app_root, "data", "output")
            env["OCR_INPUT_DIR"] = os.path.join(app_root, "data", "input")
            env["OCR_TEMP_DIR"] = os.path.join(app_root, "data", "temp")
        env["OCR_LOG_LEVEL"] = "DEBUG"

        try:
            sys.stdout = log_redirector
            sys.stderr = log_redirector

            print("日志重定向已启动，现在同时输出到终端和GUI")

            process = subprocess.Popen(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                text=True,
                bufsize=1,
                universal_newlines=True,
                env=env
            )

            output_data = []
            for line in process.stdout:
                output_data.append(line)
                print(line.rstrip())

                if status_bar:
                    progress = extract_progress_from_log(line)
                    if progress is not None:
                        log_widget.after(0, lambda p=progress: status_bar.set_status(f"处理中: {p}%完成", p))

            process.wait()

            end_time = datetime.datetime.now()
            duration_sec = max(0.0, time.perf_counter() - start_perf)

            print(f"\n{'=' * 50}")
            print(f"执行完毕！返回码: {process.returncode}")
            print(f"结束时间: {end_time.strftime('%Y-%m-%d %H:%M:%S')}")
            print(f"耗时: {duration_sec:.2f} 秒")

            output_text = ''.join(output_data)

            is_pipeline = "pipeline" in command
            no_merge_files = "未找到采购单文件" in output_text
            single_file = "只有1个采购单文件" in output_text

            if is_pipeline and (no_merge_files or single_file):
                print("完整流程中没有需要合并的文件，但其他步骤执行成功，视为成功完成")
                if status_bar:
                    log_widget.after(0, lambda: status_bar.set_status("处理完成", 100))
                log_widget.after(0, lambda: show_result_preview(command, output_text))
            else:
                if on_complete:
                    log_widget.after(0, lambda: on_complete(process.returncode, output_text))
                elif process.returncode == 0:
                    if status_bar:
                        log_widget.after(0, lambda: status_bar.set_status("处理完成", 100))
                    log_widget.after(0, lambda: show_result_preview(command, output_text))
                else:
                    if status_bar:
                        log_widget.after(0, lambda: status_bar.set_status(f"处理失败 (返回码: {process.returncode})", 0))
                    log_widget.after(0, lambda: messagebox.showerror("操作失败", f"处理失败，返回码：{process.returncode}"))

        except Exception as e:
            print(f"\n执行出错: {str(e)}")
            if status_bar:
                log_widget.after(0, lambda: status_bar.set_status(f"执行出错: {str(e)}", 0))
            log_widget.after(0, lambda: messagebox.showerror("执行错误", f"执行命令时出错: {str(e)}"))
        finally:
            sys.stdout = old_stdout
            sys.stderr = old_stderr

            _RUNNING_TASK = None
            if status_bar:
                log_widget.after(0, lambda: status_bar.set_running(False))

    Thread(target=run_in_thread).start()


def extract_progress_from_log(log_line):
    """从日志行中提取进度信息"""
    batch_match = re.search(r'处理批次 (\d+)/(\d+)', log_line)
    if batch_match:
        current = int(batch_match.group(1))
        total = int(batch_match.group(2))
        return int(current / total * 100)

    percent_match = re.search(r'(\d+)%', log_line)
    if percent_match:
        return int(percent_match.group(1))

    return None
