"""Confluence publisher unit tests."""

from __future__ import annotations

import json

import httpx
import pytest

from packages.artifacts.design import DesignArtifact, MetadataPlanItem
from packages.artifacts.requirements import RequirementsArtifact
from packages.config import Settings
from packages.integrations.confluence import (
    HttpConfluencePublisher,
    MockConfluencePublisher,
    design_doc_storage_html,
    design_doc_title,
    get_confluence_publisher,
    reset_mock_confluence_publisher,
)


def test_design_doc_title_uses_technical_design_prefix():
    title = design_doc_title("AN-29", "Account Segment Classification")
    assert title == "Technical Design — Account Segment Classification (AN-29)"


def test_design_doc_title_truncates():
    title = design_doc_title("AN-29", "x" * 300, max_len=80)
    assert title.startswith("Technical Design —")
    assert "(AN-29)" in title
    assert len(title) <= 80
    assert title.endswith("…") or title.endswith("(AN-29)")


def test_design_doc_storage_html_is_technical_design_format():
    requirements = RequirementsArtifact(
        jira_key="AN-29",
        summary="Account Segment Classification",
        acceptance_criteria=[
            "Create the Account_Segment__c custom picklist field on the Account object.",
            "Configure the field label as Account Segment.",
            "Add the following picklist values: Enterprise, Mid-Market, SMB.",
            "Set Mid-Market as the default value.",
            "Add the field to all Account page layouts.",
            "Create the Account_Segment_Required_For_Customer validation rule.",
            "Ensure the validation rule applies to all users.",
            "Customer accounts must have Account Segment before they can be saved.",
        ],
        is_clear=True,
        confidence=0.9,
        out_of_scope_items=[
            "Documentation and training.",
            "Sharing rules.",
            "Permission sets.",
            "Production deployment.",
        ],
    )
    design = DesignArtifact(
        jira_key="AN-29",
        summary="Account Segment Classification",
        approach="Custom Account picklist plus a Customer-only validation rule.",
        metadata_plan=[
            MetadataPlanItem(
                metadata_type="CustomField",
                api_name="Account_Segment__c",
                action="create",
                object="Account",
                notes="Picklist; label Account Segment; values Enterprise, Mid-Market, SMB; default Mid-Market",
            ),
            MetadataPlanItem(
                metadata_type="ValidationRule",
                api_name="Account_Segment_Required_For_Customer",
                action="create",
                object="Account",
                notes="Block save when Type is Customer and Account_Segment__c is blank",
            ),
        ],
        confidence=0.85,
    )
    html_body = design_doc_storage_html(requirements, design)

    assert "Technical Design — Account Segment Classification (AN-29)" in html_body
    for heading in (
        "1. Overview",
        "2. Scope",
        "3. Data Model",
        "4. Picklist Configuration",
        "5. Page Layout Configuration",
        "6. Validation Rule",
        "7. Processing Behavior",
        "8. Security and Access",
        "9. Deployment Components",
        "10. Testing Strategy",
        "11. Acceptance Criteria Traceability",
        "12. Implementation Summary",
    ):
        assert heading in html_body

    assert "In Scope" in html_body
    assert "Out of Scope" in html_body
    assert "Account_Segment__c" in html_body
    assert "Account Segment" in html_body
    assert "Enterprise" in html_body
    assert "Mid-Market" in html_body
    assert "SMB" in html_body
    assert "Account_Segment_Required_For_Customer" in html_body
    assert "ISPICKVAL(Type, &quot;Customer&quot;)" in html_body or 'ISPICKVAL(Type, "Customer")' in html_body
    assert "Documentation and training" in html_body
    assert "<h2>Requirements</h2>" not in html_body
    assert "Agent Nova —" not in html_body


@pytest.mark.asyncio
async def test_mock_confluence_publisher_records_create():
    publisher = MockConfluencePublisher()
    page = await publisher.create_page("ENG", "Agent Nova — AN-1: Test", "<p>hi</p>")
    assert page.id
    assert page.url.endswith(f"/spaces/ENG/pages/{page.id}")
    assert len(publisher.creates) == 1
    assert publisher.creates[0]["title"] == "Agent Nova — AN-1: Test"


@pytest.mark.asyncio
async def test_http_confluence_publisher_posts_storage_body():
    def handler(request: httpx.Request) -> httpx.Response:
        assert request.method == "POST"
        assert request.url.path.endswith("/rest/api/content")
        payload = json.loads(request.content.decode())
        assert payload["type"] == "page"
        assert payload["space"]["key"] == "ENG"
        assert payload["title"] == "Technical Design — Tier (AN-29)"
        assert payload["body"]["storage"]["representation"] == "storage"
        assert "Customer_Tier" in payload["body"]["storage"]["value"]
        return httpx.Response(
            200,
            json={
                "id": "4242",
                "title": "Technical Design — Tier (AN-29)",
                "_links": {"webui": "/spaces/ENG/pages/4242/technical-design-tier-an-29"},
            },
        )

    settings = Settings(
        confluence_provider="http",
        confluence_base_url="https://example.atlassian.net/wiki",
        confluence_space_keys="ENG,ARCH",
        confluence_email="me@example.com",
        confluence_api_token="token-123",
    )
    publisher = HttpConfluencePublisher(settings, transport=httpx.MockTransport(handler))
    page = await publisher.create_page(
        "ENG",
        "Technical Design — Tier (AN-29)",
        "<p>Customer_Tier</p>",
    )
    assert page.id == "4242"
    assert page.url == (
        "https://example.atlassian.net/wiki/spaces/ENG/pages/4242/technical-design-tier-an-29"
    )


@pytest.mark.asyncio
async def test_http_confluence_publisher_surfaces_duplicate_title_error():
    def handler(request: httpx.Request) -> httpx.Response:
        return httpx.Response(
            400,
            json={
                "statusCode": 400,
                "message": (
                    "com.atlassian.confluence.api.service.exceptions.api.BadRequestException: "
                    "A page with this title already exists: A page already exists with the same "
                    "TITLE in this space"
                ),
            },
        )

    settings = Settings(
        confluence_provider="http",
        confluence_base_url="https://example.atlassian.net/wiki",
        confluence_space_keys="ENG",
        confluence_email="me@example.com",
        confluence_api_token="token-123",
    )
    publisher = HttpConfluencePublisher(settings, transport=httpx.MockTransport(handler))
    with pytest.raises(httpx.HTTPStatusError) as exc_info:
        await publisher.create_page("ENG", "Technical Design — Dup", "<p>x</p>")
    assert "title already exists" in str(exc_info.value).lower()


def test_get_confluence_publisher_uses_http_provider():
    reset_mock_confluence_publisher()
    settings = Settings(
        confluence_provider="http",
        confluence_base_url="https://example.atlassian.net/wiki",
        confluence_space_keys="ENG",
        confluence_email="me@example.com",
        confluence_api_token="token-123",
    )
    publisher = get_confluence_publisher(settings)
    assert isinstance(publisher, HttpConfluencePublisher)


def test_confluence_write_space_falls_back_to_first_space_key():
    settings = Settings(
        confluence_space_keys="ENG,ARCH",
        confluence_write_space_key="",
    )
    assert settings.confluence_write_space == "ENG"
    settings_explicit = Settings(
        confluence_space_keys="ENG,ARCH",
        confluence_write_space_key="DOCS",
    )
    assert settings_explicit.confluence_write_space == "DOCS"
