"""Result Manager (Component F14)."""

from __future__ import annotations

from datetime import datetime

from gps_denied.core.sse import SSEEventStreamer
from gps_denied.db.repository import FlightRepository
from gps_denied.schemas import GPSPoint
from gps_denied.schemas.events import FrameProcessedEvent


class ResultManager:
    """Result consistency and publishing."""

    def __init__(self, repo: FlightRepository, sse: SSEEventStreamer) -> None:
        self.repo = repo
        self.sse = sse

    async def update_frame_result(
        self,
        flight_id: str,
        frame_id: int,
        gps_lat: float,
        gps_lon: float,
        altitude: float,
        heading: float,
        confidence: float,
        timestamp: datetime,
        refined: bool = False,
    ) -> bool:
        """Atomic DB update + SSE event publish."""

        # 1. Update DB (in the repository these are auto-committing via flush,
        # but normally F03 would wrap in a single transaction).
        await self.repo.save_frame_result(
            flight_id,
            frame_id=frame_id,
            gps_lat=gps_lat,
            gps_lon=gps_lon,
            altitude=altitude,
            heading=heading,
            confidence=confidence,
            refined=refined,
        )

        # Wait, the spec also wants Waypoints to be updated.
        # But image frames != waypoints. Waypoints are the planned route.
        # Actually in the spec it says: "Updates waypoint in waypoints table."
        # This implies updating the closest waypoint or a generated waypoint path.
        # We will follow the simplest form for now: update the waypoint if there is one corresponding.
        # Let's say we update a waypoint with id "wp_{frame_id}" for now if we know how they map,
        # or we just skip unless specified.

        # 2. Trigger SSE event
        evt = FrameProcessedEvent(
            frame_id=frame_id,
            gps=GPSPoint(lat=gps_lat, lon=gps_lon),
            altitude=altitude,
            confidence=confidence,
            heading=heading,
            timestamp=timestamp,
        )
        if refined:
            self.sse.send_refinement(flight_id, evt)
        else:
            self.sse.send_frame_result(flight_id, evt)

        return True

    async def publish_waypoint_update(self, flight_id: str, frame_id: int) -> bool:
        # Just delegates to SSE for waypoint updates, which is basically the frame result for UI
        pass
