"""Forms, surveys & appointments API tests — Phase 11.6."""
from __future__ import annotations

import pytest

from app.events.publisher import get_event_publisher
from app.events.types import ExperienceEventType
from app.tests.conftest import TENANT_A, TENANT_B, tenant_headers


async def _workspace(client, code="ws-forms"):
    resp = await client.post(
        "/api/v1/workspaces",
        json={"code": code, "name": "Workspace", "status": "active"},
        headers=tenant_headers(TENANT_A),
    )
    assert resp.status_code == 201, resp.text
    return resp.json()


async def _site(client, workspace_id: str, code="main"):
    resp = await client.post(
        "/api/v1/sites",
        json={"workspace_id": workspace_id, "code": code, "name": "Main Site"},
        headers=tenant_headers(TENANT_A),
    )
    assert resp.status_code == 201, resp.text
    return resp.json()


@pytest.mark.asyncio
async def test_health_phase_116(client):
    resp = await client.get("/health")
    assert resp.status_code == 200
    assert resp.json()["version"].startswith("0.11.10")

    caps = await client.get("/capabilities")
    body = caps.json()
    assert body["phase"] == "11.10"
    assert body["features"]["forms"] is True
    assert body["features"]["form_submissions"] is True
    assert body["features"]["surveys"] is True
    assert body["features"]["survey_responses"] is True
    assert body["features"]["appointment_pages"] is True
    assert body["features"]["appointment_booking_refs"] is True
    assert body["features"]["seo_engine"] is True
    assert body["features"]["media_refs"] is True


@pytest.mark.asyncio
async def test_form_and_submission_lifecycle(client):
    ws = await _workspace(client)
    workspace_id = ws["id"]

    form = await client.post(
        "/api/v1/forms",
        json={
            "workspace_id": workspace_id,
            "code": "contact",
            "name": "Contact Form",
            "status": "draft",
            "form_schema_json": {"fields": [{"key": "email", "type": "email"}]},
        },
        headers=tenant_headers(TENANT_A),
    )
    assert form.status_code == 201, form.text
    form_id = form.json()["id"]

    # Draft form rejects submissions
    rejected = await client.post(
        "/api/v1/form-submissions",
        json={
            "workspace_id": workspace_id,
            "form_id": form_id,
            "payload_json": {"email": "a@b.com"},
        },
        headers=tenant_headers(TENANT_A),
    )
    assert rejected.status_code == 409, rejected.text

    activated = await client.patch(
        f"/api/v1/forms/{form_id}",
        json={"status": "active", "version": form.json()["version"]},
        headers=tenant_headers(TENANT_A),
    )
    assert activated.status_code == 200, activated.text

    # Reject CRM ownership keys in payload
    bad = await client.post(
        "/api/v1/form-submissions",
        json={
            "workspace_id": workspace_id,
            "form_id": form_id,
            "payload_json": {"crm_contact_id": "123"},
        },
        headers=tenant_headers(TENANT_A),
    )
    assert bad.status_code == 422, bad.text

    submission = await client.post(
        "/api/v1/form-submissions",
        json={
            "workspace_id": workspace_id,
            "form_id": form_id,
            "payload_json": {"email": "a@b.com"},
            "crm_contact_ref": "crm://contact-1",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert submission.status_code == 201, submission.text
    assert submission.json()["status"] == "received"
    assert submission.json()["crm_contact_ref"] == "crm://contact-1"

    other = await client.get(
        f"/api/v1/form-submissions/{submission.json()['id']}",
        headers=tenant_headers(TENANT_B),
    )
    assert other.status_code == 404

    events = {e.event_type for e in get_event_publisher().published}
    assert ExperienceEventType.FORM_CREATED.value in events
    assert ExperienceEventType.FORM_SUBMISSION_RECEIVED.value in events


@pytest.mark.asyncio
async def test_survey_and_appointment_booking_refs(client):
    ws = await _workspace(client, code="ws-appt")
    workspace_id = ws["id"]
    site = await _site(client, workspace_id)

    survey = await client.post(
        "/api/v1/surveys",
        json={
            "workspace_id": workspace_id,
            "code": "nps",
            "name": "NPS",
            "status": "active",
            "questions_json": {"items": [{"key": "score", "type": "number"}]},
        },
        headers=tenant_headers(TENANT_A),
    )
    assert survey.status_code == 201, survey.text

    response = await client.post(
        "/api/v1/survey-responses",
        json={
            "workspace_id": workspace_id,
            "survey_id": survey.json()["id"],
            "answers_json": {"score": 9},
        },
        headers=tenant_headers(TENANT_A),
    )
    assert response.status_code == 201, response.text

    page = await client.post(
        "/api/v1/appointment-pages",
        json={
            "workspace_id": workspace_id,
            "site_id": site["id"],
            "code": "book",
            "name": "Book Visit",
            "status": "active",
            "booking_provider_ref": "beauty://provider-1",
            "service_ref": "beauty://service-cut",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert page.status_code == 201, page.text
    page_id = page.json()["id"]

    # Ownership keys rejected
    bad_page = await client.patch(
        f"/api/v1/appointment-pages/{page_id}",
        json={
            "availability_shell_json": {"booking_engine": True},
            "version": page.json()["version"],
        },
        headers=tenant_headers(TENANT_A),
    )
    assert bad_page.status_code == 422, bad_page.text

    booking = await client.post(
        "/api/v1/appointment-booking-refs",
        json={
            "workspace_id": workspace_id,
            "appointment_page_id": page_id,
            "external_booking_ref": "beauty://booking-99",
            "crm_contact_ref": "crm://c-2",
            "status": "pending",
        },
        headers=tenant_headers(TENANT_A),
    )
    assert booking.status_code == 201, booking.text
    assert booking.json()["external_booking_ref"] == "beauty://booking-99"

    confirmed = await client.patch(
        f"/api/v1/appointment-booking-refs/{booking.json()['id']}",
        json={"status": "confirmed", "version": booking.json()["version"]},
        headers=tenant_headers(TENANT_A),
    )
    assert confirmed.status_code == 200, confirmed.text
    assert confirmed.json()["status"] == "confirmed"

    events = {e.event_type for e in get_event_publisher().published}
    assert ExperienceEventType.SURVEY_CREATED.value in events
    assert ExperienceEventType.APPOINTMENT_BOOKING_REF_CREATED.value in events
