"""7C Forms validation semantics. Pure; no form.submit or persistence."""
from __future__ import annotations

import math

from src.domain.connectors.invoke_capabilities import (
    CAPABILITY_CONVERSION_PATTERN,
    FORMS_FAMILY_PLAN,
)
from src.domain.forms.canonical import (
    FormDefinition,
    FormField,
    contact_block_compatible_definition,
    quote_request_block_compatible_definition,
)
from src.domain.forms.validation import (
    BOOLEAN_STRING_COERCION,
    CROSS_FIELD_VALIDATION,
    DEFAULT_SERVER_INJECTION,
    ERROR_AGGREGATION,
    FORMS_VALIDATION_SEMANTICS,
    REQUIRED_CHECKBOX_MEANS,
    UNKNOWN_FIELD_POLICY,
    FormConfigurationError,
    classify_input,
    validate_form_values,
)


def _text_form(**fields: bool) -> FormDefinition:
    return FormDefinition(
        key="sample",
        fields=[
            FormField(key="name", type="text", required=fields.get("name", False)),
            FormField(key="notes", type="textarea", required=False),
        ],
    )


def test_7c_semantics_are_frozen_and_pure() -> None:
    assert FORMS_VALIDATION_SEMANTICS["status"] == "frozen"
    assert UNKNOWN_FIELD_POLICY == "reject"
    assert REQUIRED_CHECKBOX_MEANS == "boolean_present"
    assert DEFAULT_SERVER_INJECTION is False
    assert BOOLEAN_STRING_COERCION is False
    assert ERROR_AGGREGATION == "all_fields"
    assert CROSS_FIELD_VALIDATION == "deferred"
    assert FORMS_VALIDATION_SEMANTICS["persistence"] is False
    assert FORMS_VALIDATION_SEMANTICS["post_submit"] is False
    assert FORMS_VALIDATION_SEMANTICS["anti_abuse"] == "deferred_7g"
    assert CAPABILITY_CONVERSION_PATTERN["phase_7_status"] == "complete"
    assert CAPABILITY_CONVERSION_PATTERN["next_program_slice"] == "9_app_block_modernization"
    assert FORMS_FAMILY_PLAN["slices"][2] == "7c_form_validation_semantics"
    assert FORMS_FAMILY_PLAN["validation_semantics_frozen"] is True


def test_classify_missing_null_blank_distinct() -> None:
    raw = {"a": None, "b": "", "c": "   ", "d": [], "e": False, "f": 0}
    assert classify_input(raw, "missing") == "missing"
    assert classify_input(raw, "a") == "null"
    assert classify_input(raw, "b") == "blank"
    assert classify_input(raw, "c") == "blank"
    assert classify_input(raw, "d") == "empty_list"
    assert classify_input(raw, "e") == "value"
    assert classify_input(raw, "f") == "value"


def test_required_text_empty_states() -> None:
    definition = FormDefinition(
        key="sample",
        fields=[FormField(key="name", type="text", required=True)],
    )
    for raw in ({}, {"name": None}, {"name": ""}, {"name": "   "}):
        result = validate_form_values(definition, raw)
        assert result.ok is False
        assert result.errors[0].code == "required"
        assert result.values == {}


def test_optional_empty_omitted_and_default_not_injected() -> None:
    definition = FormDefinition(
        key="sample",
        fields=[FormField(key="name", type="text", required=False, default="Ada")],
    )
    for raw in ({}, {"name": None}, {"name": "  "}):
        result = validate_form_values(definition, raw)
        assert result.ok is True
        assert result.values == {}
        assert "name" not in result.values


def test_text_trims_but_does_not_lowercase() -> None:
    definition = _text_form(name=True)
    result = validate_form_values(definition, {"name": "  Jane  "})
    assert result.ok is True
    assert result.values["name"] == "Jane"


def test_number_zero_valid_and_string_literal_coerced() -> None:
    definition = FormDefinition(
        key="sample",
        fields=[FormField(key="budget", type="number", required=True)],
    )
    assert validate_form_values(definition, {"budget": 0}).values["budget"] == 0
    assert validate_form_values(definition, {"budget": "42"}).values["budget"] == 42
    assert validate_form_values(definition, {"budget": "3.5"}).values["budget"] == 3.5
    bad = validate_form_values(definition, {"budget": "1abc"})
    assert bad.errors[0].code == "invalid_number"
    typed = validate_form_values(definition, {"budget": True})
    assert typed.errors[0].code == "invalid_type"
    inf = validate_form_values(definition, {"budget": math.inf})
    assert inf.errors[0].code == "invalid_type"
    blank = validate_form_values(definition, {"budget": ""})
    assert blank.errors[0].code == "invalid_number"
    whitespace = validate_form_values(definition, {"budget": "   "})
    assert whitespace.errors[0].code == "invalid_number"


def test_checkbox_false_is_valid_even_when_required() -> None:
    definition = FormDefinition(
        key="sample",
        fields=[FormField(key="subscribe", type="checkbox", required=True)],
    )
    result = validate_form_values(definition, {"subscribe": False})
    assert result.ok is True
    assert result.values["subscribe"] is False
    missing = validate_form_values(definition, {})
    assert missing.errors[0].code == "required"
    on = validate_form_values(definition, {"subscribe": "on"})
    assert on.errors[0].code == "invalid_type"
    blank = validate_form_values(definition, {"subscribe": ""})
    assert blank.errors[0].code == "invalid_type"


def test_email_and_phone_rules() -> None:
    definition = contact_block_compatible_definition()
    ok = validate_form_values(
        definition,
        {
            "name": "Ada",
            "email": "Ada@Example.COM",
            "phone": "+1 (555) 0100",
            "message": "Hello",
        },
    )
    assert ok.ok is True
    assert ok.values["email"] == "Ada@Example.COM"
    bad_email = validate_form_values(
        definition,
        {"name": "Ada", "email": "not-an-email", "message": "Hello"},
    )
    assert "invalid_email" in {error.code for error in bad_email.errors}
    e164 = validate_form_values(
        definition,
        {"name": "Ada", "email": "a@b.c", "phone": "not a phone!", "message": "Hi"},
    )
    assert "invalid_phone" in {error.code for error in e164.errors}


def test_select_uses_value_not_label() -> None:
    definition = quote_request_block_compatible_definition()
    payload = {
        "name": "Ada",
        "email": "ada@example.com",
        "project_type": "enterprise",
        "message": "Need a roof",
    }
    labeled = validate_form_values(definition, {**payload, "project_type": "Repair"})
    assert labeled.ok is False
    assert any(error.code == "invalid_option" for error in labeled.errors)
    ok = validate_form_values(definition, {**payload, "project_type": "repair"})
    assert ok.ok is True
    assert ok.values["project_type"] == "repair"


def test_unknown_fields_rejected_and_errors_aggregate() -> None:
    definition = contact_block_compatible_definition()
    result = validate_form_values(
        definition,
        {"email": "ada@example.com", "admin": True},
    )
    codes = {(error.field, error.code) for error in result.errors}
    assert ("admin", "unknown_field") in codes
    assert ("name", "required") in codes
    assert ("message", "required") in codes
    assert result.ok is False
    assert result.values == {}


def test_hidden_is_validated_as_client_input() -> None:
    definition = FormDefinition(
        key="sample",
        fields=[FormField(key="source", type="hidden", required=True)],
    )
    assert validate_form_values(definition, {"source": "landing"}).ok is True
    assert validate_form_values(definition, {}).errors[0].code == "required"
    assert validate_form_values(definition, {"source": 1}).errors[0].code == "invalid_type"


def test_file_runtime_accepts_form_file_ref_not_strings() -> None:
    definition = quote_request_block_compatible_definition()
    base = {
        "name": "Ada",
        "email": "ada@example.com",
        "message": "Quote please",
    }
    omitted = validate_form_values(definition, base)
    assert omitted.ok is True
    present = validate_form_values(definition, {**base, "attachment": "file-id"})
    assert present.ok is False
    assert any(error.code == "invalid_type" for error in present.errors)


def test_form_key_mismatch_is_configuration_error() -> None:
    definition = contact_block_compatible_definition()
    try:
        validate_form_values(definition, {"name": "Ada"}, form_key="quote_request")
        raise AssertionError("expected FormConfigurationError")
    except FormConfigurationError as exc:
        assert exc.code == "form_key_mismatch"


def test_contact_adapter_compatible_happy_path() -> None:
    definition = contact_block_compatible_definition()
    result = validate_form_values(
        definition,
        {
            "name": "Jane Smith",
            "email": "jane@example.com",
            "phone": "1",
            "message": "Hello",
        },
        form_key="contact",
    )
    assert result.ok is True
    submission = result.submission()
    assert submission.form_key == "contact"
    assert set(submission.values) == {"name", "email", "phone", "message"}


def test_contact_honeypot_and_turnstile_are_unknown_to_field_validation() -> None:
    definition = contact_block_compatible_definition()
    result = validate_form_values(
        definition,
        {
            "name": "Ada",
            "email": "ada@example.com",
            "message": "Hi",
            "website": "https://spam.example",
            "turnstile_token": "tok",
        },
    )
    extras = {error.field for error in result.errors if error.code == "unknown_field"}
    assert extras == {"turnstile_token", "website"}


def test_provider_keys_are_unknown_fields() -> None:
    definition = contact_block_compatible_definition()
    result = validate_form_values(
        definition,
        {
            "name": "Ada",
            "email": "ada@example.com",
            "message": "Hi",
            "portal_id": "123",
        },
    )
    assert any(
        error.field == "portal_id" and error.code == "unknown_field"
        for error in result.errors
    )
