from enum import IntEnum
from typing import Optional

from pydantic import BaseModel


class DNSOpcodeID(IntEnum):
    """
    Enum representing different DNS opcode identifiers.

    Attributes:
    - Query (0): Standard query.
    - Inverse Query (1): Inverse query, obsolete.
    - Status (2): Server status request.
    - Reserved (3): Reserved, not used.
    - Notify (4): Zone change notification.
    - Update (5): Dynamic DNS update.
    - DSO Message (6): DNS Stateful Operations (DSO).
    """

    Query = 0
    Inverse_Query = 1
    Status = 2
    Reserved = 3
    Notify = 4
    Update = 5
    DSO_Message = 6


class DNSQuery(BaseModel):
    """
    The DNS query object represents a specific request made to the Domain Name System (DNS) to retrieve information about a domain or perform a DNS operation.
    This object encapsulates the necessary attributes and methods to construct and send DNS queries, specify the query type (e.g., A, AAAA, MX).

    Attributes:
    - DNS Opcode (opcode) [Optional]: The DNS opcode specifies the type of the query message.
    - DNS Opcode ID (opcode_id) [Recommended]: The DNS opcode ID specifies the normalized query message type.
    - Hostname (hostname) [Required]: The hostname or domain being queried. For example: www.example.com.
    - Packet UID (packet_uid) [Recommended]: The DNS packet identifier assigned by the program that generated the query. The identifier is copied to the response.
    - Resource Record Class (class) [Recommended]: The class of resource records being queried. See RFC1035. For example: IN.
    - Resource Record Type (type) [Recommended]: The type of resource records being queried. See RFC1035. For example: A, AAAA, CNAME, MX, and NS.
    """

    opcode: Optional[str] = None
    opcode_id: Optional[DNSOpcodeID] = None
    hostname: str
    packet_uid: Optional[int] = None
    # TODO: Update to Pydantic v2 to use Field
    # class_: Optional[str] = Field(
    #     alias="class"
    # )  # Renaming class to avoid conflict with Python keyword
    type: Optional[str] = None
