"""
Test specification types for DAZZLE IR.

This module contains test case specifications for API testing
including setup steps, actions, and assertions.
"""

from enum import StrEnum
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


class TestActionKind(StrEnum):
    """Types of test actions."""

    CREATE = "create"
    UPDATE = "update"
    DELETE = "delete"
    CALL = "call"
    GET = "get"


class TestAssertionKind(StrEnum):
    """Types of test assertions."""

    STATUS = "status"
    CREATED = "created"
    FIELD = "field"
    ERROR = "error"
    COUNT = "count"


class TestComparisonOperator(StrEnum):
    """Comparison operators for test assertions."""

    EQUALS = "equals"
    NOT_EQUALS = "not_equals"
    GREATER_THAN = "greater_than"
    LESS_THAN = "less_than"
    CONTAINS = "contains"
    NOT_CONTAINS = "not_contains"


class TestSetupStep(BaseModel):
    """
    Setup step in a test.

    Creates objects or sets up state before test action.
    """

    variable_name: str
    action: TestActionKind
    entity_name: str
    data: dict[str, Any] = Field(default_factory=dict)

    model_config = ConfigDict(frozen=True)


class TestAction(BaseModel):
    """
    Main action to test.

    Attributes:
        kind: Type of action (create, update, delete, etc.)
        target: Entity or object being acted upon
        data: Data for the action
    """

    kind: TestActionKind
    target: str  # Entity name or variable reference
    data: dict[str, Any] = Field(default_factory=dict)

    model_config = ConfigDict(frozen=True)


class TestAssertion(BaseModel):
    """
    Test assertion/expectation.

    Attributes:
        kind: Type of assertion
        field_name: Field being asserted (for FIELD assertions)
        operator: Comparison operator
        expected_value: Expected value
    """

    kind: TestAssertionKind
    field_name: str | None = None
    operator: TestComparisonOperator | None = None
    expected_value: Any | None = None
    error_message: str | None = None

    model_config = ConfigDict(frozen=True)


class TestSpec(BaseModel):
    """
    Test specification from DSL.

    Defines a test case with setup, action, and expectations.

    Attributes:
        name: Test identifier
        description: Human-readable description
        setup_steps: Objects to create before test
        action: Main action to test
        assertions: List of expected outcomes
    """

    name: str
    description: str | None = None
    setup_steps: list[TestSetupStep] = Field(default_factory=list)
    action: TestAction
    assertions: list[TestAssertion] = Field(default_factory=list)

    model_config = ConfigDict(frozen=True)
