"""
基于 pywebview 实现的跨平台 UI，需先登录方可使用
"""
from config import  cache_path,debug,version,JAVA_API_BASE,JSON_TASK_QUEUE,runing_task,runing_shop
import datetime
import json
import sys
import shutil
import os
from amazon.main import TaskMonitor
os.makedirs(cache_path,exist_ok=True)
if not debug:
    today = datetime.datetime.now().strftime("%Y_%m_%d")
    sys.stdout = open(os.path.join(cache_path,f'{today}.log'), 'a',buffering=1)
    sys.stderr = sys.stdout

import webview
import threading
import time
import requests
import subprocess


with open("version.txt","w",encoding="utf-8") as file:
    file.write(json.dumps({"version":version}))

print(f"""
========================================================
版本： {version}
========================================================

""")


# 获取当前脚本所在目录
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
APP_URL = "http://127.0.0.1:5123"
PORT = 5123


def generate_images(params):
    """供前端调用的生成图片接口"""
    from generate_api import generate
    return generate(params)


class WindowAPI:
    """暴露给 JavaScript 的窗口控制 API"""

    def __init__(self, window):
        self._window = window
        self._is_maximized = False
        window.events.maximized += lambda _: setattr(self, '_is_maximized', True)
        window.events.restored += lambda _: setattr(self, '_is_maximized', False)

    def close(self):
        sys.exit(1)
        self._window.destroy()

    def minimize(self):
        self._window.minimize()

    def maximize(self):
        self._window.maximize()

    def toggle_maximize(self):
        if self._is_maximized:
            self._window.restore()
        else:
            self._window.maximize()

    def save_image(self, url_or_data, filename='image.png'):
        """弹窗选择保存位置并下载图片。url_or_data 可为 http(s) 链接或 data:  base64"""
        import base64
        import re
        result = self._window.create_file_dialog(
            webview.SAVE_DIALOG,
            save_filename=filename,
            file_types=('图片文件 (*.png;*.jpg;*.jpeg)', '所有文件 (*.*)')
        )
        if not result:
            return {'success': False, 'error': '用户取消'}
        path = result[0] if isinstance(result, (list, tuple)) else result
        try:
            if url_or_data.startswith('data:'):
                match = re.match(r'data:image/\w+;base64,(.+)', url_or_data)
                if not match:
                    print(url_or_data)
                    print('无效的 data URL')
                    return {'success': False, 'error': '无效的 data URL'}
                data = base64.b64decode(match.group(1))
            else:
                import requests
                resp = requests.get(url_or_data, timeout=30)
                resp.raise_for_status()
                data = resp.content
            with open(path, 'wb') as f:
                f.write(data)
            return {'success': True, 'path': path}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def save_image_to_folder(self, url_or_data, dir_path, filename='image.png'):
        """将图片保存到指定文件夹。url_or_data 可为 http(s) 链接或 data: base64"""
        import base64
        import re
        path = os.path.join(dir_path, filename)
        try:
            if url_or_data.startswith('data:'):
                match = re.match(r'data:image/\w+;base64,(.+)', url_or_data)
                if not match:
                    return {'success': False, 'error': '无效的 data URL'}
                data = base64.b64decode(match.group(1))
            else:
                import requests
                resp = requests.get(url_or_data, timeout=30)
                resp.raise_for_status()
                data = resp.content
            os.makedirs(dir_path, exist_ok=True)
            with open(path, 'wb') as f:
                f.write(data)
            return {'success': True, 'path': path}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def select_folder(self):
        # 此方法会在 JavaScript 中被调用，返回选择的文件夹路径
        result = webview.windows[0].create_file_dialog(
            webview.FOLDER_DIALOG,  # 指定为文件夹对话框
            allow_multiple=False,  # 是否允许多选
            directory=''  # 初始目录
        )
        # create_file_dialog 返回的是列表（多选时）或 None
        return result[0] if result else ''

    def select_brand_xlsx_files(self):
        """品牌爬虫：选择 .xlsx 文件，允许多选，返回路径列表"""
        result = webview.windows[0].create_file_dialog(
            webview.OPEN_DIALOG,
            allow_multiple=True,
            file_types=('Excel 文件 (*.xlsx)', '所有文件 (*.*)')
        )
        print("选择的excel 文件",result)
        if not result:
            return []
        return result if isinstance(result, list) or isinstance(result, tuple) else [result]

    def select_brand_folder(self):
        """品牌爬虫：选择文件夹，返回文件夹路径（前端再请求后端展开该目录下所有 xlsx）"""
        result = webview.windows[0].create_file_dialog(
            webview.FOLDER_DIALOG,
            allow_multiple=False,
            directory=''
        )
        return result[0] if result else ''

    def save_file_from_url(self, url, default_filename='download.zip'):
        """弹窗选择保存位置，从 url 下载文件并保存。用于品牌任务结果 zip 等。"""
        if not url or not url.strip():
            return {'success': False, 'error': '下载地址为空'}
        result = self._window.create_file_dialog(
            webview.SAVE_DIALOG,
            save_filename=default_filename,
            file_types=('ZIP 压缩包 (*.zip)', '所有文件 (*.*)')
        )
        if not result:
            return {'success': False, 'error': '用户取消'}
        path = result[0] if isinstance(result, (list, tuple)) else result
        try:
            import requests
            resp = requests.get(url.strip(), timeout=120, stream=True)
            resp.raise_for_status()
            with open(path, 'wb') as f:
                for chunk in resp.iter_content(chunk_size=65536):
                    if chunk:
                        f.write(chunk)
            return {'success': True, 'path': path}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def save_template_xlsx(self):
        """弹窗选择保存位置，将品牌文档格式模板 xlsx 保存到用户选择的位置。"""
        template_name = '品牌文档格式_模板.xlsx'
        template_path = os.path.join(BASE_DIR, 'static', template_name)
        if not os.path.isfile(template_path):
            return {'success': False, 'error': '模板文件不存在'}
        result = self._window.create_file_dialog(
            webview.SAVE_DIALOG,
            save_filename=template_name,
            file_types=('Excel 文件 (*.xlsx)', '所有文件 (*.*)')
        )
        if not result:
            return {'success': False, 'error': '用户取消'}
        path = result[0] if isinstance(result, (list, tuple)) else result
        try:
            shutil.copy2(template_path, path)
            return {'success': True, 'path': path}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def save_template_zip(self):
        """弹窗选择保存位置，将品牌文档格式模板 xlsx 保存到用户选择的位置。"""
        import shutil
        template_name = '模板2-以文件夹方式上传.zip'
        template_path = os.path.join(BASE_DIR, 'static', template_name)
        if not os.path.isfile(template_path):
            return {'success': False, 'error': '模板文件不存在'}
        result = self._window.create_file_dialog(
            webview.SAVE_DIALOG,
            save_filename=template_name,
            file_types=('ZIP 文件 (*.zip)', '所有文件 (*.*)')
        )
        if not result:
            return {'success': False, 'error': '用户取消'}
        path = result[0] if isinstance(result, (list, tuple)) else result
        try:
            shutil.copy2(template_path, path)
            return {'success': True, 'path': path}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def upload_file_to_java(self, file_path, relative_path=None):
        """按本地路径读取文件并上传到 Java 后端临时目录。"""
        if not file_path or not str(file_path).strip():
            return {'success': False, 'error': '文件路径为空'}
        normalized_path = os.path.abspath(str(file_path).strip())
        if not os.path.isfile(normalized_path):
            return {'success': False, 'error': '文件不存在'}
        try:
            with open(normalized_path, 'rb') as file_obj:
                response = requests.post(
                    f"{JAVA_API_BASE}/api/files/upload",
                    files={'file': (os.path.basename(normalized_path), file_obj)},
                    data={'relativePath': str(relative_path).strip()} if relative_path else None,
                    timeout=120,
                )
            response.raise_for_status()
            payload = response.json()
            if not isinstance(payload, dict):
                return {'success': False, 'error': 'Java 返回格式错误'}
            return payload
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def open_external_url(self, url):
        if not url or not str(url).strip():
            return {'success': False, 'error': '链接为空'}
        target = str(url).strip()
        try:
            if sys.platform.startswith('win'):
                os.startfile(target)
            elif sys.platform == 'darwin':
                subprocess.Popen(['open', target])
            else:
                subprocess.Popen(['xdg-open', target])
            return {'success': True}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def enqueue_json(self, data):
        """保存任务到队列"""
        try:
            print("==============================")
            print(datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S"),"调用传入",data)
            print("==================================")
            payload = data
            if isinstance(data, str):
                payload = json.loads(data)
            if not isinstance(payload, (dict, list)):
                return {'success': False, 'error': '仅支持 JSON 对象或数组'}
            if payload.get("type") == "delete-brand-run" and payload.get("data").get("taskId") in runing_task:
                return {'success': False, 'error': '已存在正在执行的删除品牌任务'}
            # 判断当前店铺是否正在运行中
            if payload.get("data").get("items"):
                shop_name = payload["data"]["items"][0]["shopName"]
                if shop_name in runing_shop:
                    return {'success': False, 'error': '当前店铺正在执行中,请等待店铺完成之后重试'}
            JSON_TASK_QUEUE.put(payload)
            return {'success': True, 'queue_size': JSON_TASK_QUEUE.qsize()}
        except Exception as e:
            return {'success': False, 'error': str(e)}

    def get_detail_del(self,task_id):
        """获取正在执行的删除品牌任务详情"""
        task_info = runing_task.get(task_id)
        if not task_info:
            return {'success': False, 'error': '任务不存在'}
        return {'success': True, 'task_info': task_info}
    
    def stop_task(self,task_id):
        """停止正在执行的删除品牌任务"""
        task_info = runing_task.get(task_id)
        if not task_info:
            return {'success': False, 'error': '任务不存在'}
        # 这里可以设置一个标志位，实际的删除品牌任务需要定期检查这个标志位来决定是否停止
        task_info['stop_requested'] = True
        return {'success': True, 'message': '已请求停止任务'}


def start_flask():
    from app import run_app
    run_app(host='127.0.0.1', port=PORT)


def start_task_monitor():
    """启动任务监控器（在独立线程中运行）"""
    monitor = TaskMonitor()
    try:
        print(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 任务监控线程已启动")
        monitor.start()
    except Exception:
        import traceback
        print(f"[{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 任务监控线程异常退出: {traceback.format_exc()}")


def main():
    if not os.path.exists(cache_path):
        os.makedirs(cache_path,exist_ok=True)
    
    # 启动 Flask 服务
    t = threading.Thread(target=start_flask, daemon=True)
    t.start()
    
    # 启动任务监控线程
    monitor_thread = threading.Thread(target=start_task_monitor, daemon=True)
    monitor_thread.start()
    
    # 等待 Flask 启动
    time.sleep(2)

    window = webview.create_window(
        title="数富AI",
        url=APP_URL,
        width=1400,
        height=900,
        resizable=True,
        min_size=(1200, 700),
        background_color="#1a1a1a",
        frameless=False,
        easy_drag=True
    )
    api = WindowAPI(window)
    window.expose(api.close, api.minimize, api.maximize, api.toggle_maximize, generate_images, api.save_image, api.save_image_to_folder, api.select_folder, api.select_brand_xlsx_files, api.select_brand_folder,
                  api.save_file_from_url, api.save_template_xlsx,api.save_template_zip,api.upload_file_to_java,api.open_external_url,api.enqueue_json,api.get_detail_del)
    webview.start(
        debug=True,
        storage_path=cache_path,
        private_mode=False
    )


if __name__ == "__main__":
    main()
