"""MitreId — validated MITRE ATT&CK technique identifier.

Immutable value object that ensures the identifier follows the ATT&CK
format: ``T`` followed by 4 digits, optionally a dot and 3 more digits
for sub-techniques (e.g. ``T1059``, ``T1059.001``).
"""

# Enable future language features for compatibility
from __future__ import annotations

# Import re
import re

# Import dataclass from dataclasses
from dataclasses import dataclass

# Assign _MITRE_ID_RE = re.compile(r"^T\d{4}(\.\d{3})?$")
_MITRE_ID_RE = re.compile(r"^T\d{4}(\.\d{3})?$")


# Apply the @dataclass decorator
@dataclass(frozen=True, slots=True)
# Define class MitreId
class MitreId:
    """Validated MITRE ATT&CK technique identifier."""

    # value: str
    value: str

    # Define function __post_init__
    def __post_init__(self) -> None:
        """Validate that *value* matches the expected MITRE ATT&CK ID format.

        Returns:
            None
        """
        # Check: not _MITRE_ID_RE.match(self.value)
        if not _MITRE_ID_RE.match(self.value):
            # Raise ValueError
            raise ValueError(
                f"Invalid MITRE ATT&CK ID '{self.value}'. "
                # Literal argument value
                "Expected format: T1234 or T1234.001"
            )

    # Apply the @property decorator
    @property
    # Define function is_subtechnique
    def is_subtechnique(self) -> bool:
        """Return True if this identifier represents a sub-technique.

        Returns:
            bool: True when the ID contains a dot (e.g. ``T1059.001``).
        """
        # Return "." in self.value
        return "." in self.value

    # Apply the @property decorator
    @property
    # Define function parent_id
    def parent_id(self) -> str | None:
        """Return the parent technique ID (e.g. ``T1059`` for ``T1059.001``).

        Returns:
            str | None: The parent ID string, or None if this is not a sub-technique.
        """
        # Check: not self.is_subtechnique
        if not self.is_subtechnique:
            # Return None
            return None
        # Return self.value.split(".")[0]
        return self.value.split(".")[0]

    # Define function __str__
    def __str__(self) -> str:
        """Return the string representation of the MITRE ID.

        Returns:
            str: The raw identifier string (e.g. ``"T1059.001"``).
        """
        # Return self.value
        return self.value

    # Define function __eq__
    def __eq__(self, other: object) -> bool:
        """Compare this MitreId to another MitreId or a plain string.

        Args:
            other (object): The value to compare against; may be a
                :class:`MitreId` instance or a plain ``str``.

        Returns:
            bool: True if the identifiers are equal, NotImplemented for
                unsupported types.
        """
        # Check: isinstance(other, MitreId)
        if isinstance(other, MitreId):
            # Return self.value == other.value
            return self.value == other.value
        # Check: isinstance(other, str)
        if isinstance(other, str):
            # Return self.value == other
            return self.value == other
        # Return NotImplemented
        return NotImplemented

    # Define function __hash__
    def __hash__(self) -> int:
        """Return the hash of the identifier string.

        Returns:
            int: Hash value derived from the raw identifier string.
        """
        # Return hash(self.value)
        return hash(self.value)
