"""
Timer Service fuer Phasen-Countdown.

Berechnet verbleibende Zeit, Warnungen und Overtime-Status.
"""

from datetime import datetime
from typing import Dict, Any

from .models import LessonPhase, LessonSession


class PhaseTimer:
    """
    Timer Service fuer den Phasen-Countdown.

    Features:
    - Berechnet verbleibende Zeit pro Phase
    - Warnung bei 2 Minuten vor Ende
    - Overtime-Erkennung wenn Zeit abgelaufen
    """

    # Warnung X Sekunden vor Ende (2 Minuten)
    WARNING_THRESHOLD_SECONDS = 120

    def get_remaining_seconds(self, session: LessonSession) -> int:
        """
        Berechnet die verbleibende Zeit in der aktuellen Phase.

        Beruecksichtigt Pause-Zeit: Wenn pausiert, wird die Zeit seit Pause-Start
        nicht mitgezaehlt. Die kumulative Pause-Zeit (total_paused_seconds) wird
        von der verstrichenen Zeit abgezogen.

        Args:
            session: Die aktuelle Session

        Returns:
            Verbleibende Sekunden (min 0)
        """
        # Inaktive Phasen haben keinen Timer
        if session.current_phase in [LessonPhase.NOT_STARTED, LessonPhase.ENDED]:
            return 0

        if not session.phase_started_at:
            return 0

        # Phasendauer holen
        phase_id = session.current_phase.value
        duration_minutes = session.phase_durations.get(phase_id, 10)
        duration_seconds = duration_minutes * 60

        # Verstrichene Zeit berechnen (mit Pause-Beruecksichtigung)
        elapsed = self._get_effective_elapsed(session)
        remaining = duration_seconds - elapsed

        return max(0, int(remaining))

    def _get_effective_elapsed(self, session: LessonSession) -> float:
        """
        Berechnet die effektive verstrichene Zeit abzueglich Pausenzeit.

        Args:
            session: Die aktuelle Session

        Returns:
            Effektive verstrichene Sekunden
        """
        if not session.phase_started_at:
            return 0

        # Basis: Zeit seit Phasenstart
        total_elapsed = (datetime.utcnow() - session.phase_started_at).total_seconds()

        # Abzug: Kumulative Pause-Zeit
        total_elapsed -= session.total_paused_seconds

        # Wenn aktuell pausiert: Zeit seit Pause-Start auch abziehen
        if session.is_paused and session.pause_started_at:
            current_pause = (datetime.utcnow() - session.pause_started_at).total_seconds()
            total_elapsed -= current_pause

        return max(0, total_elapsed)

    def get_elapsed_seconds(self, session: LessonSession) -> int:
        """
        Berechnet die effektive verstrichene Zeit in der aktuellen Phase.

        Beruecksichtigt Pause-Zeit analog zu get_remaining_seconds.

        Args:
            session: Die aktuelle Session

        Returns:
            Verstrichene Sekunden (abzueglich Pausen)
        """
        if not session.phase_started_at:
            return 0

        if session.current_phase == LessonPhase.ENDED:
            return 0

        return int(self._get_effective_elapsed(session))

    def get_total_seconds(self, session: LessonSession) -> int:
        """
        Gibt die Gesamtdauer der aktuellen Phase in Sekunden zurueck.

        Args:
            session: Die aktuelle Session

        Returns:
            Gesamtdauer in Sekunden
        """
        if session.current_phase in [LessonPhase.NOT_STARTED, LessonPhase.ENDED]:
            return 0

        phase_id = session.current_phase.value
        duration_minutes = session.phase_durations.get(phase_id, 10)
        return duration_minutes * 60

    def get_percentage_remaining(self, session: LessonSession) -> int:
        """
        Berechnet den Prozentsatz der verbleibenden Zeit.

        Args:
            session: Die aktuelle Session

        Returns:
            Prozent (0-100)
        """
        total = self.get_total_seconds(session)
        if total == 0:
            return 0

        remaining = self.get_remaining_seconds(session)
        return round((remaining / total) * 100)

    def get_percentage_elapsed(self, session: LessonSession) -> int:
        """
        Berechnet den Prozentsatz der verstrichenen Zeit.

        Args:
            session: Die aktuelle Session

        Returns:
            Prozent (0-100)
        """
        return 100 - self.get_percentage_remaining(session)

    def is_warning(self, session: LessonSession) -> bool:
        """
        Prueft ob die Warnungszeit erreicht ist (2 Min vor Ende).

        Args:
            session: Die aktuelle Session

        Returns:
            True wenn Warnung aktiv
        """
        if session.current_phase in [LessonPhase.NOT_STARTED, LessonPhase.ENDED]:
            return False

        remaining = self.get_remaining_seconds(session)
        return 0 < remaining <= self.WARNING_THRESHOLD_SECONDS

    def is_overtime(self, session: LessonSession) -> bool:
        """
        Prueft ob die Phase ueberzogen wurde.

        Args:
            session: Die aktuelle Session

        Returns:
            True wenn Overtime
        """
        if session.current_phase in [LessonPhase.NOT_STARTED, LessonPhase.ENDED]:
            return False

        remaining = self.get_remaining_seconds(session)
        return remaining == 0

    def get_overtime_seconds(self, session: LessonSession) -> int:
        """
        Berechnet wie viele Sekunden die Phase ueberzogen wurde.

        Args:
            session: Die aktuelle Session

        Returns:
            Overtime-Sekunden (0 wenn nicht ueberzogen)
        """
        if not self.is_overtime(session):
            return 0

        elapsed = self.get_elapsed_seconds(session)
        total = self.get_total_seconds(session)
        return max(0, elapsed - total)

    def format_time(self, seconds: int) -> str:
        """
        Formatiert Sekunden als MM:SS String.

        Args:
            seconds: Sekunden

        Returns:
            Formatierte Zeit (z.B. "12:34")
        """
        minutes = seconds // 60
        secs = seconds % 60
        return f"{minutes:02d}:{secs:02d}"

    def get_phase_status(self, session: LessonSession) -> Dict[str, Any]:
        """
        Gibt den vollstaendigen Timer-Status zurueck.

        Args:
            session: Die aktuelle Session

        Returns:
            Dictionary mit Timer-Informationen
        """
        remaining = self.get_remaining_seconds(session)
        total = self.get_total_seconds(session)
        elapsed = self.get_elapsed_seconds(session)
        overtime = self.get_overtime_seconds(session)

        return {
            "remaining_seconds": remaining,
            "remaining_formatted": self.format_time(remaining),
            "total_seconds": total,
            "total_formatted": self.format_time(total),
            "elapsed_seconds": elapsed,
            "elapsed_formatted": self.format_time(elapsed),
            "percentage_remaining": self.get_percentage_remaining(session),
            "percentage_elapsed": self.get_percentage_elapsed(session),
            "percentage": self.get_percentage_remaining(session),  # Alias for Visual Timer
            "warning": self.is_warning(session),
            "overtime": self.is_overtime(session),
            "overtime_seconds": overtime,
            "overtime_formatted": self.format_time(overtime) if overtime > 0 else None,
            "is_paused": session.is_paused,
        }

    def get_lesson_timer(self, session: LessonSession) -> Dict[str, Any]:
        """
        Gibt den Timer-Status fuer die gesamte Stunde zurueck.

        Args:
            session: Die aktuelle Session

        Returns:
            Dictionary mit Stunden-Timer-Informationen
        """
        total_planned = session.get_total_duration_minutes() * 60

        if session.lesson_started_at:
            if session.lesson_ended_at:
                actual_duration = (session.lesson_ended_at - session.lesson_started_at).total_seconds()
            else:
                actual_duration = (datetime.utcnow() - session.lesson_started_at).total_seconds()
        else:
            actual_duration = 0

        return {
            "total_planned_seconds": total_planned,
            "total_planned_formatted": self.format_time(total_planned),
            "actual_duration_seconds": int(actual_duration),
            "actual_duration_formatted": self.format_time(int(actual_duration)),
            "started_at": session.lesson_started_at.isoformat() if session.lesson_started_at else None,
            "ended_at": session.lesson_ended_at.isoformat() if session.lesson_ended_at else None,
        }
