from __future__ import annotations
from dataclasses import dataclass
from math import sqrt, cos, sin, radians
from typing import Tuple


@dataclass(frozen=True)
class Point:
    """Represents a point (x, y) in 2D coordinate geometry."""
    x: float
    y: float

    # ---- basic utilities ----

    def as_tuple(self) -> Tuple[float, float]:
        return (self.x, self.y)

    def distance_to(self, other: "Point") -> float:
        """Distance between two points (distance formula)."""
        dx = other.x - self.x
        dy = other.y - self.y
        return sqrt(dx * dx + dy * dy)

    def midpoint(self, other: "Point") -> "Point":
        """Midpoint of the segment joining self and other."""
        return Point((self.x + other.x) / 2.0, (self.y + other.y) / 2.0)

    # ---- transformations ----

    def translate(self, dx: float, dy: float) -> "Point":
        """Translate point by (dx, dy)."""
        return Point(self.x + dx, self.y + dy)

    def reflect_x_axis(self) -> "Point":
        """Reflection in x-axis."""
        return Point(self.x, -self.y)

    def reflect_y_axis(self) -> "Point":
        """Reflection in y-axis."""
        return Point(-self.x, self.y)

    def rotate(self, angle_deg: float, about: "Point" | None = None) -> "Point":
        """
        Rotate the point by angle (degrees) anti-clockwise about 'about' point
        (default: origin).
        """
        if about is None:
            about = Point(0.0, 0.0)

        theta = radians(angle_deg)
        # shift to origin
        x0 = self.x - about.x
        y0 = self.y - about.y

        xr = x0 * cos(theta) - y0 * sin(theta)
        yr = x0 * sin(theta) + y0 * cos(theta)

        return Point(xr + about.x, yr + about.y)
