from __future__ import annotations

import json
from pathlib import Path
import sys
from threading import Thread

import pytest


ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "src"))
APP_DIR = ROOT / "web" / "operator-gui"

from rights_filter.server.http_app import build_server
from rights_filter.server.image_store import LocalSubmissionImageStore
from rights_filter.server.sqlite_store import CopyrighterStore


def _start(server):
    thread = Thread(target=server.serve_forever, daemon=True)
    thread.start()
    return thread


def _browser_or_skip(playwright):
    try:
        return playwright.chromium.launch(headless=True)
    except Exception as exc:
        pytest.skip(f"Playwright Chromium is not available: {exc}")


def _bootstrap_payload():
    return {
        "submissions": [
            {
                "id": "SUB-SMOKE1",
                "title": "Smoke sample",
                "asset": "/assets/case-portrait.svg",
                "riskScore": 42,
                "riskBand": "medium",
                "submittedAt": "2026-06-03 10:00",
                "submittedEpoch": 1780452000,
                "lastAnalysis": "2026-06-03 10:01",
                "applicantStatus": "검토 중",
                "decisionStatus": "unreviewed",
                "reasons": ["Naver search returned no results"],
                "providerState": {"internal": "ok", "naver": "empty", "google": "disabled", "llm": "pending"},
                "fileFacts": {"size": "320 x 240", "format": "SVG", "submitted": "2026-06-03 10:00", "analysis": "v1"},
                "derivativeNote": "브라우저 smoke test submission",
                "recommendation": {"label": "운영자 검토 필요", "detail": "검색 근거가 부족합니다."},
                "derivedPreview": {"automatic": False, "entryName": "Smoke sample", "effect": "보강 검색 필요"},
                "queryHistory": [
                    {
                        "provider": "naver",
                        "query": "Smoke sample official",
                        "status": "empty",
                        "timestamp": "2026-06-03 10:01",
                        "count": 0,
                    }
                ],
                "similar": [{"asset": "/assets/case-portrait.svg", "label": "local submission"}],
                "evidence": [
                    {
                        "id": "ev-smoke-empty",
                        "group": "naver",
                        "source": "naver",
                        "title": "Naver search returned no results",
                        "confidence": 0,
                        "query": "Smoke sample official",
                        "domain": "naver",
                        "url": "",
                        "imageUrl": "",
                        "thumbnailUrl": "",
                        "pageTitle": "",
                        "matchType": "empty",
                        "rank": "",
                        "providerScore": 0,
                        "retrievedAt": "2026-06-03 10:01",
                        "contributed": False,
                        "sourceEvidenceIds": [],
                        "status": "active",
                    }
                ],
            }
        ],
        "submissionQueue": {"label": "smoke", "folderPath": "smoke", "isActive": True},
        "providers": [{"id": "naver", "name": "Naver", "enabled": True, "quota": 100, "usage": 0, "status": "ok"}],
        "knowledgeEntries": [],
        "collectionCandidates": [],
        "corrections": [],
        "auditEvents": [],
        "coverageThresholds": {"coverageGoodRate": 70, "coverageWarnRate": 40, "queryGoodRate": 70, "queryWarnRate": 40},
        "searchCoverage": {
            "submissions": {"total": 1, "coverageSubmissions": 0},
            "queries": {"failed": 0},
            "providers": [{"id": "naver", "name": "Naver", "queryEntries": 1, "evidenceSubmissions": 0}],
        },
    }


def test_browser_smoke_suggested_query_fills_manual_query_without_running_search(tmp_path: Path):
    playwright = pytest.importorskip("playwright.sync_api")
    image_root = tmp_path / "submissions"
    image_root.mkdir()
    store = CopyrighterStore(tmp_path / "copyrighter.sqlite3")
    store.initialize()
    server = build_server(
        host="127.0.0.1",
        port=0,
        store=store,
        image_store=LocalSubmissionImageStore(image_root),
        static_dir=APP_DIR,
    )
    _start(server)
    base = f"http://127.0.0.1:{server.server_port}"

    try:
        with playwright.sync_playwright() as pw:
            browser = _browser_or_skip(pw)
            page = browser.new_page(viewport={"width": 1280, "height": 900})
            browser_errors = []
            page.on("console", lambda message: browser_errors.append(f"console:{message.type}:{message.text}"))
            page.on("pageerror", lambda error: browser_errors.append(f"pageerror:{error}"))
            page.route(
                "**/api/bootstrap",
                lambda route: route.fulfill(
                    status=200,
                    content_type="application/json",
                    body=json.dumps(_bootstrap_payload(), ensure_ascii=False),
                ),
            )
            page.goto(base + "/")
            try:
                page.wait_for_selector('#queue-body [data-select-case="SUB-SMOKE1"]', timeout=5000)
            except Exception as exc:
                pytest.fail(f"{exc}\nerrors={browser_errors}\nbody={page.locator('body').inner_text()[:1000]}")
            page.get_by_role("button", name="SUB-SMOKE1").click()
            page.get_by_role("button", name="Smoke sample 저작권").click()

            assert page.locator('[data-workbench-panel="queries"]').is_visible()
            assert page.locator("#manual-query").input_value() == "Smoke sample 저작권"
            assert page.locator("#manual-query-status").inner_text() == "추천 쿼리를 입력했습니다. 실행 버튼을 눌러 검색하세요.", browser_errors

            browser.close()
    finally:
        server.shutdown()


def test_browser_uploads_image_and_selects_new_submission(tmp_path: Path):
    playwright = pytest.importorskip("playwright.sync_api")
    image_root = tmp_path / "submissions"
    image_root.mkdir()
    upload_file = tmp_path / "smoke upload.svg"
    upload_file.write_text("<svg xmlns='http://www.w3.org/2000/svg' width='80' height='60'></svg>", encoding="utf-8")
    store = CopyrighterStore(tmp_path / "copyrighter.sqlite3")
    store.initialize()
    server = build_server(
        host="127.0.0.1",
        port=0,
        store=store,
        image_store=LocalSubmissionImageStore(image_root),
        static_dir=APP_DIR,
    )
    _start(server)
    base = f"http://127.0.0.1:{server.server_port}"

    try:
        with playwright.sync_playwright() as pw:
            browser = _browser_or_skip(pw)
            page = browser.new_page(viewport={"width": 1280, "height": 900})
            browser_errors = []
            page.on("console", lambda message: browser_errors.append(f"console:{message.type}:{message.text}"))
            page.on("pageerror", lambda error: browser_errors.append(f"pageerror:{error}"))

            page.goto(base + "/")
            page.set_input_files("#submission-image", str(upload_file))
            assert page.locator("#submission-image-name").inner_text() == "smoke upload.svg"

            page.get_by_role("button", name="사진 넣기").click()
            page.wait_for_selector('#queue-body [data-select-case="smoke-upload"]', state="attached", timeout=10000)
            page.wait_for_selector("#workbench-view", state="visible", timeout=10000)

            assert (image_root / "images" / "smoke-upload.svg").exists()
            assert "smoke-upload 사진이 추가되었습니다. 새 심사 건으로 바로 선택했습니다." in page.locator("#submission-import-status").inner_text()
            assert page.locator("#case-title").inner_text() == "smoke-upload · smoke-upload"
            assert not browser_errors

            browser.close()
    finally:
        server.shutdown()
