"""
标伙伴 · AI标书助手 — 桌面启动器
运行此文件 (或打包后的 bid_partner.exe) 即可自动启动本地服务并打开浏览器。
"""
import os
import sys
import socket
import threading
import time
import webbrowser
import urllib.request
import logging


# ── 找可用端口 ──────────────────────────────────────────────────────────────
def _find_free_port(start: int = 5000, attempts: int = 20) -> int:
    for port in range(start, start + attempts):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            try:
                s.bind(('127.0.0.1', port))
                return port
            except OSError:
                continue
    return start  # 最坏情况：直接用 5000，让 Flask 报错


PORT = _find_free_port()


# ── 日志 ────────────────────────────────────────────────────────────────────
def _setup_logging():
    if getattr(sys, 'frozen', False):
        log_dir = os.path.dirname(sys.executable)
    else:
        log_dir = os.path.dirname(os.path.abspath(__file__))
    log_path = os.path.join(log_dir, 'bid_partner.log')
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
        handlers=[logging.FileHandler(log_path, encoding='utf-8', mode='a')],
    )


# ── 启动 Flask 服务 ─────────────────────────────────────────────────────────
def _start_server():
    try:
        import app as flask_app
        flask_app.init_db()
        flask_app.app.run(
            host='127.0.0.1',
            port=PORT,
            debug=False,
            threaded=True,
            use_reloader=False,
        )
    except Exception as e:
        logging.getLogger('launcher').error(f'服务启动失败: {e}', exc_info=True)


# ── 等待服务就绪 ─────────────────────────────────────────────────────────────
def _wait_for_server(timeout: int = 60) -> bool:
    url = f'http://127.0.0.1:{PORT}'
    deadline = time.time() + timeout
    while time.time() < deadline:
        try:
            urllib.request.urlopen(url, timeout=1)
            return True
        except Exception:
            time.sleep(0.4)
    return False


# ── 主界面 (tkinter) ─────────────────────────────────────────────────────────
def _run_gui():
    import tkinter as tk
    from tkinter import ttk, font as tkfont

    URL = f'http://127.0.0.1:{PORT}'

    root = tk.Tk()
    root.title('标伙伴 · AI标书助手')
    root.geometry('400x220')
    root.resizable(False, False)
    root.configure(bg='#f5f5f5')

    # ── 标题 ──
    title_font = tkfont.Font(family='微软雅黑', size=14, weight='bold')
    tk.Label(root, text='标伙伴 · AI 标书助手', font=title_font,
             bg='#f5f5f5', fg='#1a1a2e').pack(pady=(22, 4))

    # ── 状态行 ──
    status_var = tk.StringVar(value='正在启动服务，请稍候…')
    status_lbl = tk.Label(root, textvariable=status_var,
                          font=('微软雅黑', 10), bg='#f5f5f5', fg='#555')
    status_lbl.pack(pady=4)

    # ── URL 链接 ──
    url_lbl = tk.Label(root, text='', font=('Consolas', 10),
                       bg='#f5f5f5', fg='#1a73e8', cursor='hand2')
    url_lbl.pack(pady=2)
    url_lbl.bind('<Button-1>', lambda _: webbrowser.open(URL))

    # ── 按钮区 ──
    btn_frame = tk.Frame(root, bg='#f5f5f5')
    btn_frame.pack(pady=18)

    open_btn = ttk.Button(btn_frame, text='打开浏览器',
                          command=lambda: webbrowser.open(URL),
                          state='disabled', width=14)
    open_btn.pack(side='left', padx=8)

    quit_btn = ttk.Button(btn_frame, text='退出程序',
                          command=root.destroy, width=10)
    quit_btn.pack(side='left', padx=8)

    # ── 版本信息 ──
    tk.Label(root, text='单机版  ·  本地运行  ·  数据不上传',
             font=('微软雅黑', 8), bg='#f5f5f5', fg='#aaa').pack(pady=(0, 10))

    # ── 后台轮询，服务就绪后更新 UI ──
    def _on_ready():
        status_var.set('服务已就绪 ✓')
        status_lbl.config(fg='#2e7d32')
        url_lbl.config(text=URL)
        open_btn.config(state='normal')
        webbrowser.open(URL)

    def _on_timeout():
        status_var.set('启动超时，请查看 bid_partner.log')
        status_lbl.config(fg='#c62828')

    def _check():
        if _wait_for_server():
            root.after(0, _on_ready)
        else:
            root.after(0, _on_timeout)

    threading.Thread(target=_check, daemon=True).start()
    root.mainloop()


# ── 无图形模式（仅控制台） ────────────────────────────────────────────────────
def _run_headless():
    print(f'[标伙伴] Starting server on port {PORT} ...')
    if _wait_for_server():
        print(f'[标伙伴] Ready  →  http://127.0.0.1:{PORT}')
        webbrowser.open(f'http://127.0.0.1:{PORT}')
        # 阻塞，直到用户 Ctrl+C
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            print('[标伙伴] Shutting down.')
    else:
        print('[标伙伴] Server did not start within 60 s. Check bid_partner.log.')


# ── 入口 ─────────────────────────────────────────────────────────────────────
def main():
    _setup_logging()

    server_thread = threading.Thread(target=_start_server, daemon=True)
    server_thread.start()

    try:
        _run_gui()
    except Exception:
        _run_headless()


if __name__ == '__main__':
    main()
