from __future__ import annotations

import unittest
from pathlib import Path


PROJECT_ROOT = Path(__file__).resolve().parents[1]
STATIC_ROOT = PROJECT_ROOT / "arr_web" / "static"


class TaskLogStaticContractTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.html = (STATIC_ROOT / "index.html").read_text(encoding="utf-8")
        cls.styles = (STATIC_ROOT / "styles.css").read_text(encoding="utf-8")
        cls.script = (STATIC_ROOT / "app.js").read_text(encoding="utf-8")

    def test_header_utility_replaces_mobile_dashboard_entry(self) -> None:
        self.assertIn('id="task-log-trigger"', self.html)
        self.assertIn('<a class="task-log-link"', self.html)
        self.assertIn('aria-haspopup="dialog"', self.html)
        self.assertIn('aria-controls="task-log-dialog"', self.html)
        self.assertNotIn("手机看板", self.html)
        self.assertNotIn('class="h5-link"', self.html)

    def test_console_is_outside_the_daily_panel_and_inside_one_dialog(self) -> None:
        daily_start = self.html.index('id="panel-daily"')
        daily_end = self.html.index('id="panel-monthly"')
        daily_panel = self.html[daily_start:daily_end]
        self.assertNotIn('id="process-log"', daily_panel)
        self.assertEqual(self.html.count('id="process-log"'), 1)
        self.assertEqual(self.html.count('id="task-log-dialog"'), 1)
        self.assertGreater(
            self.html.index('id="task-log-dialog"'),
            self.html.index("</main>"),
        )
        for required_id in (
            'id="process-title"',
            'id="trace-live-state"',
            'id="refresh-trace"',
            'id="copy-trace"',
            'id="close-task-log"',
        ):
            self.assertIn(required_id, self.html)

    def test_dialog_open_close_and_polling_contract(self) -> None:
        self.assertIn('$("#task-log-trigger").addEventListener("click", (event) => {', self.script)
        self.assertIn("event.preventDefault();", self.script)
        self.assertEqual(self.script.count("openTaskLog();"), 1)
        self.assertIn('$("#close-task-log").addEventListener("click", closeTaskLog)', self.script)
        self.assertIn('$("#task-log-dialog").addEventListener("close", clearTracePoll)', self.script)
        self.assertIn("|| !taskLogIsOpen()", self.script)
        self.assertNotIn("showLog", self.script)
        self.assertNotIn('{ scroll: true }', self.script)

    def test_daily_rows_are_not_task_log_controls(self) -> None:
        render_start = self.script.index("function renderJobs(jobs)")
        render_end = self.script.index("function reviewPrice(value)", render_start)
        renderer = self.script[render_start:render_end]
        self.assertNotIn('class="job-row', renderer)
        self.assertNotIn('data-job-id=', renderer)
        self.assertNotIn('tabindex="0" role="button"', renderer)
        self.assertNotIn('aria-selected=', renderer)

        handler_start = self.script.index('$("#jobs-body").addEventListener("click"')
        handler_end = self.script.index('$("#daily-price-review-body")', handler_start)
        handlers = self.script[handler_start:handler_end]
        self.assertNotIn('$("#jobs-body").addEventListener("keydown"', handlers)
        self.assertNotIn('closest("[data-job-id]")', handlers)
        self.assertNotIn("selectJob(", handlers)
        self.assertNotIn(".job-row", self.styles)

    def test_upload_keeps_progress_inline_without_opening_log(self) -> None:
        self.assertIn('id="upload-progress"', self.html)
        self.assertIn('id="upload-progress-track"', self.html)
        self.assertIn('role="progressbar"', self.html)
        self.assertIn("DAILY_UPLOAD_PROGRESS_STAGES", self.script)
        self.assertIn("function startUploadProgress()", self.script)
        self.assertIn("function finishUploadProgress(success, label)", self.script)
        upload_start = self.script.index("async function handleUpload()")
        upload_end = self.script.index("\n  async function loadMonthsAndAnalytics", upload_start)
        upload_handler = self.script[upload_start:upload_end]
        self.assertIn("startUploadProgress()", upload_handler)
        self.assertIn("finishUploadProgress", upload_handler)
        self.assertNotIn("openTaskLog()", upload_handler)
        self.assertNotIn("showLog: true", upload_handler)

    def test_dialog_reuses_responsive_accessible_visual_system(self) -> None:
        self.assertIn(".task-log-link:hover", self.styles)
        self.assertIn(".task-log-link:active", self.styles)
        self.assertIn(".task-log-dialog::backdrop", self.styles)
        self.assertIn(".upload-progress-track", self.styles)
        self.assertIn(".upload-progress.is-success", self.styles)
        self.assertIn("max-height: calc(100dvh - 32px)", self.styles)
        self.assertIn("@media (max-width: 700px)", self.styles)
        self.assertIn("@media (prefers-reduced-motion: reduce)", self.styles)


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