"""FrameState — per-frame mutable processing record (ARCH-02).

PATTERNS.md §6.1 explicitly mandates `slots=True, frozen=False` here:
processor.py mutates this object during frame handling. The field list
mirrors the current `FrameResult` defined in `core/processor.py` lines
~52-62. All fields default-initialize so the dataclass can be constructed
with just `frame_id`, matching the existing `FrameResult(frame_id)`
constructor signature.

The actual rename of consumer call-sites from `FrameResult` to
`FrameState` happens in Plan 07 (orchestrator rename); Phase 1 only
introduces this type.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
    from gps_denied.schemas import GPSPoint


# Forward import: TrackingState lives in core/processor.py today and is
# moved here only as a type annotation. We avoid a hard import at module
# level so that core/processor.py remains the source of truth in Phase 1.
# Plan 07 will pull TrackingState into hot_types proper.
TrackingState = "TrackingState"  # type: ignore[assignment]


@dataclass(slots=True)
class FrameState:
    """Intermediate result of processing a single frame (mutable).

    Mirrors stage1's `core.processor.FrameResult` field set; default
    values let `FrameState(frame_id=N)` reconstruct the existing
    `FrameResult(frame_id)` semantics.
    """

    frame_id: int = 0
    gps: "Optional[GPSPoint]" = None
    confidence: float = 0.0
    tracking_state: str = "normal"   # mirrors TrackingState.NORMAL string value
    vo_success: bool = False
    alignment_success: bool = False
