import json
import tempfile
from pathlib import Path

from src.domain.codegen.app_sdk import app_sdk_files
from src.domain.codegen.auth_users_adapter import auth_users_adapter_files
from src.domain.project_auth.bounded_migration import (
    apply_bounded_auth_migration,
    compile_bounded_auth_migration,
)
from src.domain.codegen.repo_export import select_publishable_paths


CONTRACT = {
    "routes": {"admin_panel_path": "/admin", "customer_login_path": "/login"},
    "capabilities": {"auth": {"methods": ["passwordless"], "password": False}},
}


def _seed(root: Path) -> None:
    for path, content in {
        **auth_users_adapter_files("react_app", {"capabilities": {"auth": {"methods": ["passwordless"], "password": False}}}),
        **app_sdk_files("react_app"),
        "functions/api/auth/forgot-password.js": "// p2hs-auth-password\n",
        "functions/api/auth/reset-password.js": "// p2hs-auth-password\n",
        "src/lib/p2hs-app.js": "// p2hs-app legacy\n",
        ".github/workflows/deploy.yml": "name: Deploy to Cloudflare Pages\nuses: cloudflare/wrangler-action\nsteps:\n- run: npm install\n",
        ".gitignore": "p2hs/\n",
    }.items():
        target = root / path
        target.parent.mkdir(parents=True, exist_ok=True)
        target.write_text(content, encoding="utf-8")


def test_bounded_plan_does_not_project_unrelated_catalog_paths():
    with tempfile.TemporaryDirectory() as raw:
        root = Path(raw)
        _seed(root)
        plan = compile_bounded_auth_migration(root, "react_app", CONTRACT)
        assert not any("records" in path or "forms" in path or "bookings" in path for path in plan.expected_changed_paths)
        assert "src/lib/p2hs-app.js" in plan.expected_changed_paths
        assert "functions/api/auth/forgot-password.js" in plan.expected_changed_paths
        assert "package-lock.json" in plan.expected_changed_paths


def test_bounded_migration_is_idempotent_and_metadata_is_exportable():
    with tempfile.TemporaryDirectory() as raw:
        root = Path(raw)
        _seed(root)
        plan = compile_bounded_auth_migration(root, "react_app", CONTRACT)
        first = apply_bounded_auth_migration(root, plan)
        second = apply_bounded_auth_migration(root, plan)
        assert first["changed"]
        assert second["changed"] == []
        assert not (root / "functions/api/auth/forgot-password.js").exists()
        assert not (root / "functions/api/auth/reset-password.js").exists()
        assert "!p2hs/managed-runtime.json" in (root / ".gitignore").read_text()
        assert set(select_publishable_paths([
            "p2hs/managed-runtime.json", "p2hs/dependency-build.json", "p2hs/project-state.json"
        ])) == {"p2hs/managed-runtime.json", "p2hs/dependency-build.json"}
        manifest = json.loads((root / "p2hs/managed-runtime.json").read_text())
        assert manifest["components"]["auth_password_surface"]["admitted"] is False


def test_bounded_password_target_preserves_password_surface():
    with tempfile.TemporaryDirectory() as raw:
        root = Path(raw)
        _seed(root)
        password_contract = {
            "routes": {"admin_panel_path": "/admin", "customer_login_path": "/login"},
            "capabilities": {"auth": {"methods": ["password"], "password": True}},
        }
        plan = compile_bounded_auth_migration(root, "react_app", password_contract)
        assert any(o.operation_class == "AUTH_PASSWORD_SURFACE_PRESERVE" for o in plan.operations)
        apply_bounded_auth_migration(root, plan)
        assert (root / "functions/api/auth/forgot-password.js").is_file()
        assert (root / "functions/api/auth/reset-password.js").is_file()


def test_bounded_migration_repairs_only_shared_auth_compatibility_export():
    with tempfile.TemporaryDirectory() as raw:
        root = Path(raw)
        _seed(root)
        records = root / "functions/_lib/p2hs-records.mjs"
        records.parent.mkdir(parents=True, exist_ok=True)
        records.write_text("// p2hs-records adapter\nexport const records = true;\n", encoding="utf-8")
        plan = compile_bounded_auth_migration(root, "react_app", CONTRACT)
        assert "functions/_lib/p2hs-records.mjs" in plan.expected_changed_paths
        assert not any("records/" in path for path in plan.expected_changed_paths)
        apply_bounded_auth_migration(root, plan)
        assert "export function sessionAuthorization" in records.read_text()
