"""Adopt an existing SSR app. Owned routing and greenfield prompts stay as they are."""

from __future__ import annotations

import json
import subprocess

import pytest
from pydantic import ValidationError

from src.domain.adopt.codegen_policy import apply_adopt_contract, plan_backend_change, prompt_lines
from src.domain.adopt.compatibility import build_compatibility_report, compare_contract, evaluate_static_generate
from src.domain.adopt.contract import (
    SSR_ON_P2HS,
    AdoptAttachment,
    DataAccess,
    ExternalEndpoint,
    Projection,
    RouteRef,
    greenfield_contract,
    select_project_mode,
)
from src.domain.adopt.data_access import enforce_data_access
from src.domain.adopt.dispatcher import decide_request
from src.domain.adopt.edge_dispatch import edge_dispatch_source
from src.domain.adopt.import_scan import projection_allowed, scan_import
from src.domain.adopt.session_bridge import plan_session_exchange
from src.domain.adopt.verification import assess_endpoint
from src.domain.codegen.platform_backend import compact_platform_backend_for_prompt
from src.domain.codegen.prompt_wrapper import build_platform_backend_capabilities_section
from src.domain.hosting.bff_indirection import failover_requires_git, resolve_upstream
from src.domain.hosting.routing_plane import CloudflareRoutingProvider
from src.domain.hosting.runtime.worker_source import worker_entry


def _route() -> dict:
    return {
        "target_kind": "cloudflare_pages",
        "project_ref": "pref",
        "project_id": "proj-1",
        "environment": "production",
        "target_url": "https://p2hs-pref.pages.dev",
        "bff_origin": "https://cloud-a.example",
        "script_name": "p2hs-prod-pref",
    }


def _endpoint(**overrides) -> ExternalEndpoint:
    payload = {
        "id": "orders",
        "browser_prefix": "/api",
        "origin": "https://api.customer.com",
        "upstream_prefix": "/v1",
        "verified": True,
    }
    payload.update(overrides)
    return ExternalEndpoint(**payload)


def _active_external(**overrides) -> AdoptAttachment:
    payload = {
        "backend_source": "external_runtime_only",
        "backend_write_policy": "frozen",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "external_endpoints",
        "attachment_status": "active",
        "external_endpoints": [_endpoint()],
        "allowed_routes": [RouteRef(method="GET", path="/api/orders", endpoint_id="orders")],
        "deployment_id": "sha-1",
        "data_access": DataAccess(methods=["GET"], operator_confirmed=True),
    }
    payload.update(overrides)
    return AdoptAttachment(**payload)


def _validation_message(payload: dict) -> str:
    with pytest.raises(ValidationError) as caught:
        AdoptAttachment(**payload)
    return str(caught.value)


def test_greenfield_stays_owned_static_and_cloud_only():
    contract = greenfield_contract()
    assert contract["project_mode"] == "owned"
    assert contract["has_external_api"] is False
    assert contract["ssr_on_p2hs"] is SSR_ON_P2HS is False
    assert contract["hosting_profile"] == "w4p_static"
    assert contract["customer_backend"] is None
    assert select_project_mode(user_requested_migrate=False, adopt_signal=False) == "owned"


def test_repo_access_and_verified_endpoints_stay_in_adopt():
    assert select_project_mode(user_requested_migrate=False, adopt_signal=True) == "adopt"
    assert select_project_mode(user_requested_migrate=True, adopt_signal=True) == "migrate"
    attachment = _active_external()
    assert attachment.project_mode == "adopt"
    assert attachment.ssr_on_p2hs is False
    assert attachment.customer_backend is None
    assert attachment.edge_record()["customer_backend"] is None
    assert "legacy_customer_backend" not in attachment.edge_record()


def test_attachment_rejects_reserved_prefix_documents_role_and_ssr():
    message = _validation_message({
        "backend_source": "external_runtime_only",
        "backend_write_policy": "frozen",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "external_endpoints",
        "external_endpoints": [{
            "id": "bad",
            "role": "api",
            "browser_prefix": "/api/_p2hs",
            "origin": "https://api.customer.com",
            "upstream_prefix": "/v1",
        }],
    })
    assert "reserved" in message.lower() or "/api/_p2hs" in message
    extra = _validation_message({
        "backend_source": "co_located",
        "backend_write_policy": "frozen",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "worker_projection",
        "customer_origin": "https://api.customer.com",
    })
    assert "customer_origin" in extra
    ssr = _validation_message({
        "backend_source": "co_located",
        "backend_write_policy": "frozen",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "worker_projection",
        "ssr_on_p2hs": True,
    })
    assert "ssr_on_p2hs" in ssr


def test_write_policy_and_projection_ownership():
    writable = _validation_message({
        "backend_source": "separate",
        "backend_write_policy": "writable",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "external_endpoints",
    })
    assert "writable" in writable.lower()
    adapter = _validation_message({
        "backend_source": "co_located",
        "backend_write_policy": "frozen",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "worker_projection",
        "customer_hosted_attachment": "adapter_pr",
    })
    assert "adapter" in adapter.lower()
    separate = _validation_message({
        "backend_source": "separate",
        "backend_write_policy": "frozen",
        "backend_repository": "none",
        "p2hs_hosted_runtime": "worker_projection",
        "projections": [{
            "method": "GET",
            "path": "/api/orders",
            "status": "projected_and_verified",
            "source": "frontend_repo",
        }],
    })
    assert "backend repository" in separate.lower()
    assert projection_allowed(
        backend_source="separate", backend_repo_available=False, portable=True,
    ) == "unavailable_until_external_endpoint"
    assert projection_allowed(
        backend_source="co_located", backend_repo_available=False, portable=True,
    ) == "frontend_repo"


def test_detected_external_api_does_not_route_and_active_does():
    detected = AdoptAttachment(
        backend_source="external_runtime_only",
        backend_write_policy="frozen",
        backend_repository="none",
        p2hs_hosted_runtime="external_endpoints",
        attachment_status="detected",
        external_endpoints=[_endpoint(verified=False)],
        discovered_routes=[RouteRef(method="GET", path="/api/orders", endpoint_id="orders")],
    )
    assert detected.has_external_api is True
    assert detected.routing_active is False
    waiting = decide_request(detected.edge_record(), "/api/orders", "GET")
    assert waiting.action == "reject"
    assert waiting.reason == "external_api_unavailable"
    platform = decide_request(detected.edge_record(), "/api/_p2hs/connectors/slack/send", "POST")
    assert platform.action == "platform_bff"
    assert platform.path == "/api/connectors/slack/send"

    active = _active_external()
    routed = decide_request(active.edge_record(), "/api/orders", "GET")
    assert routed.action == "external_api"
    assert routed.origin == "https://api.customer.com/v1/orders"
    hidden = decide_request(active.edge_record(), "/api/secret", "GET")
    assert hidden.action == "reject"
    page = decide_request(active.edge_record(), "/pricing", "GET")
    assert page.action == "artifact"


def test_longest_prefix_wins_and_reserved_prefix_is_not_proxied():
    attachment = _active_external(
        external_endpoints=[
            _endpoint(),
            _endpoint(id="v2", browser_prefix="/api/v2", upstream_prefix="/v2"),
        ],
        allowed_routes=[
            RouteRef(method="GET", path="/api/orders", endpoint_id="orders"),
            RouteRef(method="GET", path="/api/v2/orders", endpoint_id="v2"),
        ],
    )
    decision = decide_request(attachment.edge_record(), "/api/v2/orders", "GET")
    assert decision.origin == "https://api.customer.com/v2/orders"
    record = attachment.edge_record()
    record["allowed_routes"].append({
        "method": "GET",
        "path": "/api/_p2hs/connectors/slack/send",
        "endpoint_id": "orders",
    })
    reserved = decide_request(record, "/api/_p2hs/connectors/slack/send", "GET")
    assert reserved.action == "platform_bff"


def test_owned_upstream_is_unchanged_and_adopt_split_is_kv_only():
    owned = resolve_upstream(_route(), "https://proj-pref.sites.p2hs.com/api/records")
    assert owned.plane == "bff"
    assert owned.url == "https://cloud-a.example/api/records"
    page = resolve_upstream(_route(), "https://proj-pref.sites.p2hs.com/admin")
    assert page.plane == "artifact"

    route = _route()
    route["adopt"] = _active_external().edge_record()
    platform = resolve_upstream(
        route,
        "https://proj-pref.sites.p2hs.com/api/_p2hs/connectors/slack/send?x=1",
        "POST",
    )
    assert platform.plane == "bff"
    assert platform.url == "https://cloud-a.example/api/connectors/slack/send?x=1"
    external = resolve_upstream(route, "https://proj-pref.sites.p2hs.com/api/orders")
    assert external.plane == "external"
    assert external.url == "https://api.customer.com/v1/orders"
    assert external.git_commit_required is False
    static_page = resolve_upstream(route, "https://proj-pref.sites.p2hs.com/pricing")
    assert static_page.plane == "artifact"
    assert static_page.url.startswith("https://p2hs-pref.pages.dev/")
    assert failover_requires_git(_route(), route) is False


def test_worker_projection_does_not_send_existing_routes_to_the_bff():
    attachment = AdoptAttachment(
        backend_source="co_located",
        backend_write_policy="frozen",
        backend_repository="none",
        p2hs_hosted_runtime="worker_projection",
        attachment_status="active",
        deployment_id="sha-1",
        data_access=DataAccess(operator_confirmed=True),
        projections=[
            Projection(method="GET", path="/api/orders", status="projected_and_verified", source="frontend_repo"),
            Projection(
                method="POST",
                path="/api/files",
                status="unavailable_until_external_endpoint",
                source="frontend_repo",
            ),
            Projection(method="POST", path="/api/search", status="delegated_to_p2hs_cloud", source="frontend_repo"),
        ],
    )
    route = _route()
    route["adopt"] = attachment.edge_record()
    projected = resolve_upstream(route, "https://proj-pref.sites.p2hs.com/api/orders")
    assert projected.plane == "project_worker"
    missing = resolve_upstream(route, "https://proj-pref.sites.p2hs.com/api/files", "POST")
    assert missing.plane == "reject"
    delegated = decide_request(attachment.edge_record(), "/api/search", "POST")
    assert delegated.reason == "delegated_to_p2hs_cloud"


def test_session_exchange_keeps_their_session_and_core_authority():
    public = plan_session_exchange("public")
    assert public["app_user"] is None
    assert public["authority"] == "p2hs_core"
    bridged = plan_session_exchange("https://api.customer.com/session")
    assert bridged["grant"] == "p2hs_app_user"
    assert bridged["verify_server_side"] == "https://api.customer.com/session"
    assert bridged["browser_receives_customer_secret"] is False


def test_writable_codegen_stays_in_adopt_and_does_not_deploy_their_backend():
    connected = plan_backend_change(
        user_requested_migrate=False, write_policy="writable", cloud_has_capability=False,
    )
    assert connected["project_mode"] == "adopt"
    assert connected["action"] == "gap_pr"
    assert connected["customer_ci_deploys"] is True
    assert connected["p2hs_deploys_backend"] is False
    covered = plan_backend_change(
        user_requested_migrate=False, write_policy="writable", cloud_has_capability=True,
    )
    assert covered["action"] == "use_platform_prefix"
    assert covered["pr"] is False
    frozen = plan_backend_change(
        user_requested_migrate=False, write_policy="frozen", cloud_has_capability=False,
    )
    assert frozen["action"] == "no_repo_change"
    assert frozen["customer_hosted_attachment"] == "edge"
    refine = plan_backend_change(
        user_requested_migrate=False,
        write_policy="writable",
        cloud_has_capability=False,
        change_kind="refinement",
    )
    assert refine["action"] == "refine_existing"
    assert plan_backend_change(
        user_requested_migrate=True, write_policy="writable", cloud_has_capability=False,
    )["project_mode"] == "migrate"


def test_greenfield_prompt_does_not_gain_adopt_rules():
    from src.domain.codegen.prompt_wrapper import _DEPLOYMENT_CONTEXT

    assert "Do not generate a local replica or call a customer origin" in _DEPLOYMENT_CONTEXT
    bare = build_platform_backend_capabilities_section({"contract_name": "PlatformBackendCapabilities"})
    assert "external_endpoints" not in bare
    attachment = _active_external(
        backend_source="separate",
        backend_write_policy="writable",
        backend_repository="https://github.com/customer/api",
        p2hs_hosted_runtime="external_endpoints",
    )
    capabilities = apply_adopt_contract(
        {"contract_name": "PlatformBackendCapabilities", "backend": {}},
        attachment,
    )
    assert capabilities["backend"]["customer_backend"] is None
    section = build_platform_backend_capabilities_section(capabilities)
    assert "Stay in adopt" in section
    assert "Their CI/CD deploys" in section
    assert compact_platform_backend_for_prompt(capabilities)["adopt"]["platform_api_prefix"] == "/api/_p2hs"
    frozen_lines = prompt_lines({"project_mode": "adopt", "backend_write_policy": "frozen"})
    assert any("frozen" in line.lower() for line in frozen_lines)


def test_import_scan_candidates_do_not_activate_routing():
    server = scan_import({"server/api/orders.ts": "export default function handler() {}"})
    assert "server_surface" in server["signals"]
    assert server["routing_active"] is False
    quiet = scan_import({"pages/index.vue": "<h1>Hello</h1>"})
    assert quiet["has_external_api"] is False
    assert quiet["ask_user"] is False
    assert quiet["project_mode"] == "owned"

    described = scan_import({"openapi.yaml": "openapi: 3.0.0\n"})
    assert described["has_external_api"] is True
    assert described["attachment_status"] == "detected"
    assert described["routing_active"] is False
    assert described["candidates"][0]["activates_routing"] is False
    assert described["candidates"][0]["kind"] == "description_file"

    browser = scan_import({"app.vue": "const rows = await $fetch('https://api.customer.com/orders')"})
    assert "browser_api" in browser["signals"]
    assert browser["routing_active"] is False
    assert browser["candidates"][0]["origin"] == "https://api.customer.com/orders"

    secret = "super-secret-value"
    scanned = scan_import({".env": f"API_TOKEN=https://user:{secret}@api.customer.com\n"})
    assert secret not in json.dumps(scanned)
    assert scanned["candidates"][0]["origin_withheld"] is True

    reserved = scan_import({"openapi.json": '{"paths": {"/api/_p2hs/records": {}}}\n'})
    assert reserved["reserved_claims"]
    assert reserved["routing_active"] is False


def test_deployment_mismatch_fails_closed_and_static_checks_are_separate():
    bad = assess_endpoint(
        expected_deployment_id="sha-1",
        origin="https://api.customer.com",
        reachable=True,
        routes_respond=True,
        tls_valid=True,
        redirects_valid=True,
        session_ok=True,
        http_status=200,
        document={"deployment_id": "other"},
    )
    assert bad["ok"] is False
    assert "deployment_mismatch" in bad["reasons"]
    stale = assess_endpoint(
        expected_deployment_id="sha-1",
        origin="http://localhost:3000",
        reachable=True,
        routes_respond=True,
        tls_valid=False,
        redirects_valid=True,
        session_ok=True,
        http_status=200,
        document={"deployment_id": "sha-1"},
    )
    assert "stale_origin" in stale["reasons"]
    assert stale["ok"] is False

    verified = compare_contract(
        {"method": "GET", "path": "/api/orders", "request_fields": [], "response_fields": ["id"], "portable": True},
        {"method": "GET", "path": "/api/orders", "request_fields": [], "response_fields": ["id"], "limitations": ["no live stock"]},
    )
    assert verified["status"] == "projected_with_limitations"
    assert verified["passing"] is True
    blocked = compare_contract({"portable": False, "customer_chose_cloud": False}, None)
    assert blocked["status"] == "unavailable_until_external_endpoint"
    chosen = compare_contract({"portable": False, "customer_chose_cloud": True}, None)
    assert chosen["status"] == "delegated_to_p2hs_cloud"
    report = build_compatibility_report([
        {
            "id": "orders",
            "expected": {"method": "GET", "path": "/api/orders", "portable": True},
            "actual": {"method": "GET", "path": "/api/orders"},
        },
        {"id": "files", "expected": {"portable": False}, "actual": None},
    ])
    assert report["presented_as_working"] == ["orders"]

    shell = evaluate_static_generate(
        generate_succeeded=True,
        expected_routes=["/pricing"],
        emitted_routes=["/pricing"],
        browser_calls=[{"url": "/api/orders"}, {"url": "/api/_p2hs/records"}],
        configured_prefixes=["/api"],
        server_only_missing=["stock"],
        platform_calls_use_session=True,
    )
    assert shell["ready"] is False
    assert shell["checks"][3]["name"] == "server_only_data_present"
    assert shell["checks"][3]["passed"] is False


def test_data_access_is_default_deny_and_is_not_widened():
    policy = DataAccess(methods=["GET"], operator_confirmed=True)
    enforce_data_access(policy, method="GET", allowlist_methods={"GET"}, fields=[])
    with pytest.raises(Exception) as denied:
        enforce_data_access(policy, method="POST", allowlist_methods={"GET", "POST"}, fields=[])
    assert denied.value.code == "method_not_allowed"
    with pytest.raises(Exception) as copied:
        enforce_data_access(policy, method="GET", allowlist_methods={"GET"}, fields=["email"])
    assert copied.value.code == "copy_denied"


def test_edge_dispatcher_strips_platform_prefix_and_proxies_allowlisted_apis():
    source = edge_dispatch_source()
    assert "customer_ssr_origin" not in source
    assert "Set-Cookie" not in source
    dispatcher = CloudflareRoutingProvider._dispatcher_source(
        CloudflareRoutingProvider.__new__(CloudflareRoutingProvider),
        "sites.p2hs.com",
    )
    assert "p2hsAdoptDispatch" in dispatcher
    assert "customer_ssr_origin" not in dispatcher
    entry = worker_entry()
    assert entry.index('"/api/_p2hs"') < entry.index("dispatchApplication")

    script = source + r"""
const calls = [];
const incoming = new URL("https://app.example/api/_p2hs/connectors/slack/send");
const stripped = await p2hsAdoptDispatch(
  incoming,
  new Request(incoming),
  { adopt: { project_mode: "adopt", has_external_api: true, attachment_status: "detected" } },
  async () => new Response("no"),
);
const externalUrl = new URL("https://app.example/api/orders");
const proxied = await p2hsAdoptDispatch(
  externalUrl,
  new Request(externalUrl, { headers: {
    cookie: "__Host-p2hs_access=secret; theme=light",
    authorization: "Bearer secret",
    "x-request-id": "req-1",
  } }),
  { project_id: "project-1", project_ref: "pref", adopt: {
      project_mode: "adopt",
      has_external_api: true,
      attachment_status: "active",
      p2hs_hosted_runtime: "external_endpoints",
      data_access: { methods: ["GET"] },
      external_endpoints: [{ id: "orders", browser_prefix: "/api", origin: "https://api.customer.com", upstream_prefix: "/v1" }],
      allowed_routes: [{ method: "GET", path: "/api/orders", endpoint_id: "orders" }],
  } },
  async (url, init) => {
    calls.push({
      url,
      cookie: init.headers.get("cookie"),
      authorization: init.headers.get("authorization"),
      projectId: init.headers.get("x-p2hs-project-id"),
      projectRef: init.headers.get("x-p2hs-project-ref"),
      publicOrigin: init.headers.get("x-p2hs-public-origin"),
      correlation: init.headers.get("x-p2hs-correlation-id"),
    });
    return new Response("ok", { status: 200 });
  },
);
const unavailable = await p2hsAdoptDispatch(
  new URL("https://app.example/api/orders"),
  new Request("https://app.example/api/orders"),
  { adopt: { project_mode: "adopt", has_external_api: true, attachment_status: "detected", external_endpoints: [{ browser_prefix: "/api" }] } },
  async () => new Response("no"),
);
process.stdout.write(JSON.stringify({
  pathname: incoming.pathname,
  stripped: stripped,
  proxied: proxied.status,
  cookie: calls[0].cookie,
  authorization: calls[0].authorization,
  projectId: calls[0].projectId,
  projectRef: calls[0].projectRef,
  publicOrigin: calls[0].publicOrigin,
  correlation: calls[0].correlation,
  upstream: calls[0].url,
  unavailable: unavailable.status,
}));
"""
    result = subprocess.run(
        ["node", "--input-type=module", "-e", script],
        capture_output=True,
        text=True,
        encoding="utf-8",
        check=False,
    )
    assert result.returncode == 0, result.stderr
    payload = json.loads(result.stdout)
    assert payload["pathname"] == "/api/connectors/slack/send"
    assert payload["stripped"] is None
    assert payload["proxied"] == 200
    assert payload["upstream"] == "https://api.customer.com/v1/orders"
    assert payload["cookie"] == "theme=light"
    assert payload["authorization"] is None
    assert payload["projectId"] == "project-1"
    assert payload["projectRef"] == "pref"
    assert payload["publicOrigin"] == "https://app.example"
    assert payload["correlation"] == "req-1"
    assert payload["unavailable"] == 404
