"""Status bar widgets for Prezo."""

from __future__ import annotations

from datetime import datetime, timezone
from typing import TYPE_CHECKING

from rich.text import Text
from textual.reactive import reactive
from textual.widgets import Static

if TYPE_CHECKING:
    from textual.timer import Timer


def format_progress_bar(current: int, total: int, width: int = 20) -> str:
    """Generate a progress bar string.

    Args:
        current: Current position (0-indexed)
        total: Total number of items
        width: Width of the progress bar in characters

    Returns:
        Progress bar string like "████████░░░░░░░░░░░░"

    """
    if total <= 0:
        return "░" * width

    progress = (current + 1) / total
    filled = int(progress * width)
    empty = width - filled

    return "█" * filled + "░" * empty


def format_time(seconds: int) -> str:
    """Format seconds as HH:MM:SS or MM:SS."""
    if seconds < 0:
        return "-" + format_time(-seconds)

    hours, remainder = divmod(seconds, 3600)
    minutes, secs = divmod(remainder, 60)

    if hours > 0:
        return f"{hours}:{minutes:02d}:{secs:02d}"
    return f"{minutes}:{secs:02d}"


class StatusBar(Static):
    """Combined status bar showing progress, clock, and elapsed time."""

    current: reactive[int] = reactive(0)
    total: reactive[int] = reactive(1)
    show_clock: reactive[bool] = reactive(True)
    show_elapsed: reactive[bool] = reactive(True)
    show_countdown: reactive[bool] = reactive(False)
    countdown_minutes: reactive[int] = reactive(0)
    # Incremental reveal indicator
    reveal_current: reactive[int] = reactive(-1)  # -1 = not in reveal mode
    reveal_total: reactive[int] = reactive(0)
    # Timer running state
    timer_running: reactive[bool] = reactive(True)
    # Time budget for pacing indicator (0 = disabled)
    time_budget_minutes: reactive[int] = reactive(0)

    def __init__(self, **kwargs) -> None:
        """Initialize the status bar."""
        super().__init__(**kwargs)
        self._start_time: datetime | None = None
        self._elapsed_when_paused: float = 0.0  # Accumulated time when paused
        self._timer: Timer | None = None

    def on_mount(self) -> None:
        """Start the timer on mount."""
        self._start_time = datetime.now(tz=timezone.utc)
        self._timer = self.set_interval(1.0, self._tick)

    def _tick(self) -> None:
        """Timer callback to refresh the display."""
        self.refresh()

    def render(self) -> Text:
        """Render the status bar content."""
        result = Text()

        # Progress part
        bar = format_progress_bar(self.current, self.total, width=20)
        progress = f" {bar} {self.current + 1}/{self.total}"
        result.append(progress)

        # Reveal indicator (shows remaining list items)
        if self.reveal_current >= 0 and self.reveal_total > 0:
            remaining = self.reveal_total - self.reveal_current - 1
            if remaining > 0:
                result.append(f" [+{remaining}]")

        # Pacing indicator (if time budget is set)
        pacing = self._get_pacing_indicator()
        if pacing:
            result.append("    ")
            result.append_text(pacing)

        # Clock part
        clock_parts = []
        if self.show_clock:
            clock_parts.append(
                datetime.now(tz=timezone.utc).astimezone().strftime("%H:%M:%S"),
            )

        if self.show_elapsed and self._start_time:
            elapsed_secs = self._get_elapsed_seconds()
            # Show pause indicator when timer is stopped
            pause_indicator = " ⏸" if not self.timer_running else ""
            clock_parts.append(f"+{format_time(elapsed_secs)}{pause_indicator}")

        if self.show_countdown and self.countdown_minutes > 0 and self._start_time:
            total_secs = self.countdown_minutes * 60
            elapsed_secs = self._get_elapsed_seconds()
            remaining = total_secs - elapsed_secs
            clock_parts.append(f"-{format_time(remaining)}")

        if clock_parts:
            # Add separator if we have pacing or progress
            result.append("    ")
            result.append(" │ ".join(clock_parts))

        result.append(" ")
        return result

    def _get_pacing_indicator(self) -> Text | None:
        """Get the pacing indicator with color based on time budget.

        Returns colored indicator:
        - Green (▲ -Xm) if more than 10% ahead
        - Red (▼ +Xm) if more than 10% behind
        - None if no time budget or on track

        """
        if self.time_budget_minutes <= 0 or self.total <= 0:
            return None

        elapsed_secs = self._get_elapsed_seconds()
        total_budget_secs = self.time_budget_minutes * 60

        # Expected time for current slide position
        # (current is 0-indexed, so current+1 gives slides completed)
        expected_secs = (total_budget_secs / self.total) * (self.current + 1)

        # Calculate difference (positive = behind, negative = ahead)
        diff_secs = elapsed_secs - expected_secs
        diff_pct = diff_secs / expected_secs if expected_secs > 0 else 0

        # More than 10% threshold
        if diff_pct > 0.1:
            # Behind schedule - need to speed up (red background, white text)
            diff_mins = int(abs(diff_secs) / 60)
            diff_remaining = int(abs(diff_secs) % 60)
            if diff_mins > 0:
                indicator = f" ▼ +{diff_mins}m{diff_remaining:02d}s "
            else:
                indicator = f" ▼ +{diff_remaining}s "
            return Text(indicator, style="bold white on red")
        if diff_pct < -0.1:
            # Ahead of schedule (green background, white text)
            diff_mins = int(abs(diff_secs) / 60)
            diff_remaining = int(abs(diff_secs) % 60)
            if diff_mins > 0:
                indicator = f" ▲ -{diff_mins}m{diff_remaining:02d}s "
            else:
                indicator = f" ▲ -{diff_remaining}s "
            return Text(indicator, style="bold white on green")

        # On track - no indicator needed
        return None

    def _get_elapsed_seconds(self) -> int:
        """Get total elapsed seconds, accounting for pauses."""
        if not self._start_time:
            return 0
        if self.timer_running:
            current_elapsed = datetime.now(tz=timezone.utc) - self._start_time
            return int(current_elapsed.total_seconds() + self._elapsed_when_paused)
        # When paused, just return the accumulated time
        return int(self._elapsed_when_paused)

    def reset_timer(self) -> None:
        """Reset the elapsed timer."""
        self._start_time = datetime.now(tz=timezone.utc)
        self._elapsed_when_paused = 0.0
        self.timer_running = True
        self.refresh()

    def toggle_timer(self) -> None:
        """Start or stop the elapsed timer."""
        if self.timer_running:
            # Pausing: save current elapsed time
            if self._start_time:
                current_elapsed = datetime.now(tz=timezone.utc) - self._start_time
                self._elapsed_when_paused += current_elapsed.total_seconds()
            self.timer_running = False
        else:
            # Resuming: reset start time (accumulated time is preserved)
            self._start_time = datetime.now(tz=timezone.utc)
            self.timer_running = True
        self.refresh()

    def toggle_clock(self) -> None:
        """Cycle through clock display modes."""
        if self.show_clock and not self.show_elapsed:
            self.show_elapsed = True
        elif self.show_clock and self.show_elapsed and not self.show_countdown:
            if self.countdown_minutes > 0:
                self.show_countdown = True
            else:
                self.show_clock = False
                self.show_elapsed = False
        elif self.show_countdown:
            self.show_clock = False
            self.show_elapsed = False
            self.show_countdown = False
        else:
            self.show_clock = True
            self.show_elapsed = False

    def watch_current(self, value: int) -> None:
        """React to current slide changes."""
        self.refresh()

    def watch_total(self, value: int) -> None:
        """React to total slides changes."""
        self.refresh()

    def watch_show_clock(self, value: bool) -> None:
        """React to clock visibility changes."""
        self.refresh()

    def watch_show_elapsed(self, value: bool) -> None:
        """React to elapsed time visibility changes."""
        self.refresh()

    def watch_reveal_current(self, value: int) -> None:
        """React to reveal indicator changes."""
        self.refresh()

    def watch_reveal_total(self, value: int) -> None:
        """React to reveal total changes."""
        self.refresh()

    def watch_timer_running(self, value: bool) -> None:
        """React to timer running state changes."""
        self.refresh()

    def watch_time_budget_minutes(self, value: int) -> None:
        """React to time budget changes."""
        self.refresh()


# Keep these for backwards compatibility and separate use
class ProgressBar(Static):
    """A progress bar widget showing slide progress."""

    current: reactive[int] = reactive(0)
    total: reactive[int] = reactive(1)

    def __init__(self, current: int = 0, total: int = 1, **kwargs) -> None:
        """Initialize the progress bar.

        Args:
            current: Current slide index (0-based).
            total: Total number of slides.
            **kwargs: Additional arguments for Static widget.

        """
        super().__init__(**kwargs)
        self.current = current
        self.total = total

    def render(self) -> str:
        """Render the progress bar."""
        bar = format_progress_bar(self.current, self.total, width=30)
        return f" {bar} {self.current + 1}/{self.total} "

    def watch_current(self, value: int) -> None:
        """React to current position changes."""
        self.refresh()

    def watch_total(self, value: int) -> None:
        """React to total count changes."""
        self.refresh()


class ClockDisplay(Static):
    """A clock widget showing current time, elapsed, and countdown."""

    show_clock: reactive[bool] = reactive(True)
    show_elapsed: reactive[bool] = reactive(True)
    show_countdown: reactive[bool] = reactive(False)
    countdown_minutes: reactive[int] = reactive(0)

    def __init__(self, **kwargs) -> None:
        """Initialize the clock display."""
        super().__init__(**kwargs)
        self._start_time: datetime | None = None
        self._timer: Timer | None = None

    def on_mount(self) -> None:
        """Start the clock timer on mount."""
        self._start_time = datetime.now(tz=timezone.utc)
        self._timer = self.set_interval(1.0, self._update_time)

    def _update_time(self) -> None:
        """Timer callback to update the display."""
        self.refresh()

    def render(self) -> str:
        """Render the clock display."""
        parts = []

        if self.show_clock:
            now = datetime.now(tz=timezone.utc).astimezone()
            parts.append(now.strftime("%H:%M:%S"))

        if self.show_elapsed and self._start_time:
            elapsed = datetime.now(tz=timezone.utc) - self._start_time
            elapsed_secs = int(elapsed.total_seconds())
            parts.append(f"+{format_time(elapsed_secs)}")

        if self.show_countdown and self.countdown_minutes > 0 and self._start_time:
            total_secs = self.countdown_minutes * 60
            elapsed = datetime.now(tz=timezone.utc) - self._start_time
            remaining = total_secs - int(elapsed.total_seconds())
            parts.append(f"-{format_time(remaining)}")

        return " │ ".join(parts) if parts else ""

    def reset_timer(self) -> None:
        """Reset the elapsed timer."""
        self._start_time = datetime.now(tz=timezone.utc)
        self.refresh()

    def toggle_clock(self) -> None:
        """Cycle through clock display modes."""
        if self.show_clock and not self.show_elapsed:
            self.show_elapsed = True
        elif self.show_clock and self.show_elapsed and not self.show_countdown:
            if self.countdown_minutes > 0:
                self.show_countdown = True
            else:
                self.show_clock = False
                self.show_elapsed = False
        elif self.show_countdown:
            self.show_clock = False
            self.show_elapsed = False
            self.show_countdown = False
        else:
            self.show_clock = True
