"""HEL-230: 提醒管理页通栏三块与三步发送流的结构/响应式契约。"""

from __future__ import annotations

import threading
import unittest
from functools import partial
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
WEB = ROOT / "web"

try:
    from playwright.sync_api import sync_playwright
except ImportError:  # pragma: no cover
    sync_playwright = None


class RemindersPageSourceContractTests(unittest.TestCase):
    def test_admin_html_order_and_send_flow(self) -> None:
        html = (WEB / "admin.html").read_text(encoding="utf-8")
        self.assertIn('data-page="reminders"', html)
        self.assertIn('id="pending-reminders-card"', html)
        self.assertIn('id="reminder-history-card"', html)
        self.assertIn('id="send-reminder-card"', html)
        self.assertIn('class="send-flow"', html)
        self.assertIn('class="sf-step"', html)
        self.assertIn('id="pick-count"', html)
        self.assertIn('id="reminderForm"', html)
        self.assertIn('id="reminderCompanyList"', html)
        self.assertIn('id="reminder-type"', html)
        self.assertIn('id="reminder-content"', html)
        self.assertIn('id="reminder-deadline"', html)
        self.assertIn('id="send-btn"', html)
        self.assertIn('id="send-hint"', html)
        self.assertIn('id="reminder-tbody"', html)
        self.assertIn('id="reminder-tabs"', html)
        self.assertIn('id="reminder-detail-drawer"', html)
        self.assertIn("design-system.css?v=10", html)
        self.assertIn("app.js?v=15", html)
        pending = html.index('id="pending-reminders-card"')
        history = html.index('id="reminder-history-card"')
        send = html.index('id="send-reminder-card"')
        self.assertLess(pending, history)
        self.assertLess(history, send)
        reminders = html[html.index('data-page="reminders"') : html.index("新增公司弹窗")]
        self.assertNotIn("grid-1-2", reminders)
        self.assertEqual(reminders.count('class="sf-step"'), 3)
        self.assertIn("选择接收公司", reminders)
        self.assertIn("填写提醒内容", reminders)
        self.assertIn("设定截止并发送", reminders)

    def test_app_js_keeps_real_reminder_apis(self) -> None:
        js = (WEB / "app.js").read_text(encoding="utf-8")
        self.assertIn('label.className = "pick"', js)
        self.assertIn("function updatePickCount", js)
        self.assertIn("function syncPendingPicks", js)
        self.assertIn("/api/admin/reminders/pending", js)
        self.assertIn("/api/admin/reminders/manual", js)
        self.assertIn("/api/admin/reminders/send", js)
        self.assertIn("/api/admin/reminders/scan", js)
        self.assertIn("function loadAdminRemindersPending", js)
        self.assertIn("function loadAdminRemindersHistory", js)
        self.assertIn("function openReminderDetailDrawer", js)
        self.assertIn("initAdminReminders()", js)
        self.assertIn("dataset.companyId", js)

    def test_design_system_send_flow_uses_tokens(self) -> None:
        css = (WEB / "design-system.css").read_text(encoding="utf-8")
        self.assertIn(".send-flow", css)
        self.assertIn(".sf-step", css)
        self.assertIn(".pick", css)
        self.assertIn("minmax(0, 1.5fr)", css)
        block_start = css.index("提醒管理：三步发送流")
        block = css[block_start:]
        self.assertIn("var(--border)", block)
        self.assertIn("var(--accent-soft)", block)
        self.assertIn("var(--accent)", block)
        self.assertIn("@media (max-width: 1100px)", block)
        self.assertNotRegex(block, r"#[0-9a-fA-F]{3,8}")
        self.assertNotRegex(block, r"rgb\(")
        self.assertNotIn("box-shadow: 0 0", block)


def _chromium_available() -> bool:
    try:
        import ctypes.util

        return bool(ctypes.util.find_library("atk-1.0"))
    except Exception:
        return False


@unittest.skipUnless(sync_playwright, "playwright 未安装，跳过布局冒烟")
@unittest.skipUnless(_chromium_available(), "系统缺少 chromium 依赖库（如 libatk），跳过布局冒烟")
class RemindersPageLayoutSmokeTests(unittest.TestCase):
    """桌面三列 / 窄屏竖排，360 / 820 / 1440 无页面级横向溢出。"""

    @classmethod
    def setUpClass(cls) -> None:
        handler = partial(SimpleHTTPRequestHandler, directory=str(WEB))
        cls.httpd = ThreadingHTTPServer(("127.0.0.1", 0), handler)
        cls.port = cls.httpd.server_address[1]
        cls.thread = threading.Thread(target=cls.httpd.serve_forever, daemon=True)
        cls.thread.start()
        cls.base = f"http://127.0.0.1:{cls.port}"

    @classmethod
    def tearDownClass(cls) -> None:
        cls.httpd.shutdown()
        cls.httpd.server_close()

    def _open_reminders(self, page, width: int) -> None:
        page.route("**/app.js**", lambda route: route.abort())
        page.set_viewport_size({"width": width, "height": 900})
        page.goto(f"{self.base}/admin.html")
        page.evaluate(
            """() => {
              document.querySelectorAll('.app-view').forEach((el) => {
                el.classList.toggle('is-active', el.dataset.page === 'reminders');
              });
              const list = document.getElementById('reminderCompanyList');
              if (list && !list.children.length) {
                ['A公司', 'B公司', '郑州金牛建业煤炭有限责任公司'].forEach((name, i) => {
                  const label = document.createElement('label');
                  label.className = 'pick';
                  label.innerHTML = '<input type="checkbox" name="company" value="' + (i + 1) + '">' + name;
                  if (i < 2) label.querySelector('input').checked = true;
                  list.append(label);
                });
              }
            }"""
        )

    def test_send_flow_columns_and_no_page_overflow(self) -> None:
        html = (WEB / "admin.html").read_text(encoding="utf-8")
        self.assertIn("app.js?v=15", html)
        with sync_playwright() as p:
            browser = p.chromium.launch()
            page = browser.new_page()
            self._open_reminders(page, 1440)
            cols_wide = page.evaluate(
                "() => getComputedStyle(document.querySelector('.send-flow')).gridTemplateColumns"
            )
            self.assertEqual(len(cols_wide.split()), 3, f"桌面端应为三列，实际: {cols_wide}")
            overflow_wide = page.evaluate(
                "() => document.documentElement.scrollWidth > document.documentElement.clientWidth + 1"
            )
            self.assertFalse(overflow_wide, "1440px 出现页面级横向溢出")

            self._open_reminders(page, 900)
            cols_narrow = page.evaluate(
                "() => getComputedStyle(document.querySelector('.send-flow')).gridTemplateColumns"
            )
            self.assertEqual(len(cols_narrow.split()), 1, f"窄屏应为单列，实际: {cols_narrow}")

            for width in (360, 820, 1440):
                self._open_reminders(page, width)
                overflow = page.evaluate(
                    "() => document.documentElement.scrollWidth > document.documentElement.clientWidth + 1"
                )
                self.assertFalse(overflow, f"{width}px 出现页面级横向溢出")
            browser.close()


if __name__ == "__main__":
    unittest.main()
