"""Sleep schedule viewer screen.

Shows the creature's sleep/wake schedule with a visual clock
and allows adjusting the schedule.
"""

from __future__ import annotations

from textual.app import ComposeResult
from textual.containers import Container, VerticalScroll
from textual.screen import Screen
from textual.widgets import Button, Footer, Header, Input, Label, Static

from sibilance.api.types import CreatureStatus


def _hour_label(hour: float) -> str:
    """Format a world hour as HH:MM."""
    h = int(hour)
    m = int((hour - h) * 60)
    return f"{h:02d}:{m:02d}"


def _sleep_bar(sleep_hour: float, wake_hour: float, current_hour: float, width: int = 24) -> str:
    """Render a 24-hour visual bar showing sleep and wake periods."""
    bar: list[str] = []
    for i in range(width):
        h = (i / width) * 24.0
        # Handle overnight sleep (e.g., sleep 22:00, wake 06:00)
        if sleep_hour > wake_hour:
            asleep = h >= sleep_hour or h < wake_hour
        else:
            asleep = sleep_hour <= h < wake_hour

        if abs(h - current_hour) < (24.0 / width):
            bar.append("◆")  # current time marker
        elif asleep:
            bar.append("░")  # sleeping
        else:
            bar.append("█")  # awake

    return "".join(bar)


class SleepScreen(Screen):
    """View and adjust the creature's sleep schedule."""

    DEFAULT_CSS = """
    SleepScreen {
        layout: vertical;
    }

    #sleep-header {
        dock: top;
        height: 1;
        padding: 0 2;
        background: $surface;
        color: $primary;
        text-style: bold;
        border-bottom: solid $secondary;
    }

    #sleep-scroll {
        height: 1fr;
        background: $background;
        padding: 1 2;
        scrollbar-color: $secondary;
        scrollbar-color-hover: $text-muted;
        scrollbar-color-active: $primary;
    }

    #sleep-adjust {
        dock: bottom;
        height: 5;
        padding: 0 2;
        background: $surface;
        border-top: solid $secondary;
    }

    #sleep-adjust Input {
        width: 12;
        margin: 0 1 0 0;
    }

    #sleep-adjust Button {
        margin: 0 1 0 0;
        min-width: 10;
        height: 1;
        background: $panel;
        color: $text-muted;
        border: none;
    }

    #sleep-adjust Button:hover {
        background: $secondary;
        color: $foreground;
    }
    """

    def __init__(self, **kwargs: object) -> None:
        super().__init__(**kwargs)
        self._busy = False

    def compose(self) -> ComposeResult:
        yield Header(show_clock=True)
        yield Label("Sleep Schedule", id="sleep-header")
        yield VerticalScroll(id="sleep-scroll")
        with Container(id="sleep-adjust"):
            yield Label("[#8888aa]Adjust: sleep hour, wake hour[/]", markup=True)
            yield Input(placeholder="Sleep (0-23)", id="input-sleep-hour")
            yield Input(placeholder="Wake (0-23)", id="input-wake-hour")
            yield Button("Update", id="btn-update-sleep")
        yield Footer()

    def on_mount(self) -> None:
        self.run_worker(self._load_schedule(), name="load-sleep")

    async def _load_schedule(self) -> None:
        try:
            api = self.app.api  # type: ignore[attr-defined]
            schedule = await api.get_sleep_schedule()

            scroll = self.query_one("#sleep-scroll", VerticalScroll)
            scroll.remove_children()

            # Status
            status = "[#7b68ee]💤 Asleep[/]" if schedule.is_asleep else "[#6bcb77]☀ Awake[/]"
            scroll.mount(Static(f"Status: {status}", markup=True))

            # Schedule details
            scroll.mount(
                Static(
                    f"\n[#8888aa]Sleep:[/] [#e8e8ff]{_hour_label(schedule.sleep_hour)}[/]  "
                    f"[#8888aa]Wake:[/] [#e8e8ff]{_hour_label(schedule.wake_hour)}[/]  "
                    f"[#8888aa]Now:[/] [#e8e8ff]{_hour_label(schedule.current_world_hour)}[/]",
                    markup=True,
                )
            )

            # Visual bar
            bar = _sleep_bar(schedule.sleep_hour, schedule.wake_hour, schedule.current_world_hour)
            scroll.mount(
                Static(
                    f"\n[#4a4a6a]0h                  24h[/]\n"
                    f"[#7b68ee]{bar}[/]\n"
                    f"[#4a4a6a]█=awake  ░=sleep  ◆=now[/]",
                    markup=True,
                )
            )

            # Pre-fill inputs with current values
            self.query_one("#input-sleep-hour", Input).value = str(int(schedule.sleep_hour))
            self.query_one("#input-wake-hour", Input).value = str(int(schedule.wake_hour))

        except Exception as exc:
            self.notify(f"Error: {exc}", severity="error", timeout=5)

    async def on_button_pressed(self, event: Button.Pressed) -> None:
        if event.button.id != "btn-update-sleep" or self._busy:
            return

        sleep_str = self.query_one("#input-sleep-hour", Input).value.strip()
        wake_str = self.query_one("#input-wake-hour", Input).value.strip()

        try:
            sleep_h = float(sleep_str)
            wake_h = float(wake_str)
        except ValueError:
            self.notify("Enter valid hours (0-23)", severity="warning", timeout=3)
            return

        if not (0 <= sleep_h < 24 and 0 <= wake_h < 24):
            self.notify("Hours must be 0-23", severity="warning", timeout=3)
            return

        self._busy = True
        try:
            api = self.app.api  # type: ignore[attr-defined]
            result = await api.set_sleep_schedule(sleep_h, wake_h)
            if result.success:
                self.notify("Schedule updated!", timeout=3)
                # Reload to show updated bar
                self.run_worker(self._load_schedule(), name="reload-sleep")
            else:
                self.notify("Update failed", severity="error", timeout=3)
        except Exception as exc:
            self.notify(f"Error: {exc}", severity="error", timeout=5)
        finally:
            self._busy = False

    def refresh_from_creature(self, creature: CreatureStatus) -> None:
        pass
