"""PR-Worker-Pool-Registry-1C — /internal/worker/jobs/recap + recap context.

3 항목 (단독 실행 기준 PASS; 같은 파일 sequential 한계 = test fixture isolation follow-up):
  1. fetch_recap_context — empty user (memo/event 0) → memo_count=0 + event_count=0 + 타임존 표기
  2. /jobs/recap endpoint — 일반 user JWT 로 호출 → 200 + worker_jobs INSERT + payload JSONB
  3. payload size guard — fetch_recap_context monkeypatch 로 거대 context 반환 → 413
"""

from __future__ import annotations

import json
import os
import sys

import pytest
import pytest_asyncio

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "app"))

from httpx import ASGITransport, AsyncClient
from sqlalchemy import text
from sqlalchemy.ext.asyncio import async_sessionmaker

from _worker_pool_helpers import (
    _make_engine,
    cleanup_worker_jobs,
    ensure_user,
    fetch_worker_job,
    get_database_url,
    mint_access_token,
)


@pytest_asyncio.fixture
async def env_setup(monkeypatch):
    monkeypatch.setenv("LAPTOP_WORKER_BOT_USERNAME", "laptop-worker-bot")


@pytest.mark.asyncio
async def test_fetch_recap_context_shape(env_setup):
    """fetch_recap_context — 시그니처 + 빈 user 시 0/0 + KST 타임존 표기."""
    from services.worker_recap_context import fetch_recap_context

    owner_id = await ensure_user("test-recap-empty-1c")
    engine = _make_engine()
    sm = async_sessionmaker(engine, expire_on_commit=False)
    try:
        async with sm() as session:
            ctx = await fetch_recap_context(session, user_id=owner_id, days=7)
    finally:
        await engine.dispose()

    assert ctx["user_id"] == owner_id
    assert ctx["days"] == 7
    assert ctx["timezone"] == "Asia/Seoul"
    assert isinstance(ctx["memos"], list)
    assert isinstance(ctx["events"], list)
    assert ctx["memo_count"] == len(ctx["memos"])
    assert ctx["event_count"] == len(ctx["events"])
    # 신규 user 이므로 event 0
    assert ctx["event_count"] == 0


@pytest.mark.asyncio
async def test_recap_endpoint_creates_worker_job(env_setup):
    """/jobs/recap 호출 → 200 + worker_jobs INSERT."""
    from main import app

    owner_id = await ensure_user("test-recap-endpoint-1c")
    token = mint_access_token("test-recap-endpoint-1c")
    try:
        async with AsyncClient(
            transport=ASGITransport(app=app), base_url="http://test"
        ) as c:
            r = await c.post(
                "/internal/worker/jobs/recap",
                json={"days": 7},
                headers={"Authorization": f"Bearer {token}"},
            )
        assert r.status_code == 200, r.text
        js = r.json()
        assert "job_id" in js
        assert js["memo_count"] >= 0
        assert js["event_count"] >= 0
        assert js["payload_bytes"] > 0
        assert "payload_compacted" in js
        assert "omitted_memos" in js
        # DB verify
        job = await fetch_worker_job(js["job_id"])
        assert job is not None
        # payload 는 JSONB dict 로 저장됨
    finally:
        await cleanup_worker_jobs("recap")


@pytest.mark.asyncio
async def test_recap_payload_413_when_oversize(env_setup, monkeypatch):
    """payload 1MB 초과 시 413 (사용자 결정 2026-05-19 cap 1MB)."""
    from api import internal_worker as iw_mod
    from main import app

    owner_id = await ensure_user("test-recap-413-1c")
    token = mint_access_token("test-recap-413-1c")

    async def fake_fetch(session, user_id, days=7):
        return {
            "user_id": user_id,
            "days": days,
            "period_start": "2026-05-12T00:00:00+09:00",
            "period_end": "2026-05-19T00:00:00+09:00",
            "timezone": "Asia/Seoul",
            # ~1.2MB raw payload (compaction 후에도 cap 초과 가정)
            "memos": [{"id": i, "title": "x" * 6000} for i in range(200)],
            "events": [],
            "memo_count": 200,
            "event_count": 0,
            "summary_stats": {
                "total_memos": 200,
                "memos_kept": 200,
                "omitted_memos": 0,
                "top_n": 200,
                "memos_by_day": {},
                "memos_by_kind": {},
            },
            "payload_compacted": False,
        }

    monkeypatch.setattr(iw_mod, "fetch_recap_context", fake_fetch)

    async with AsyncClient(
        transport=ASGITransport(app=app), base_url="http://test"
    ) as c:
        r = await c.post(
            "/internal/worker/jobs/recap",
            json={"days": 7},
            headers={"Authorization": f"Bearer {token}"},
        )
    assert r.status_code == 413, r.text
    assert "bytes" in r.json()["detail"]
    assert "after compaction" in r.json()["detail"]
