from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from ui.tab_bar import TabBar, _FallbackGtk
from ui.view_model import TabVM


def _tabs() -> tuple[TabVM, ...]:
    return (
        TabVM(id="alerts", label="⚠ Alerts", badge_count=2, badge_level="err"),
        TabVM(id="codex", label="Codex", badge_count=1, badge_level="warn"),
        TabVM(id="claude", label="Claude Code", badge_count=0, badge_level=""),
    )


def test_tab_bar_renders_tabs_badges_and_active_state() -> None:
    bar = TabBar(_tabs(), "codex", lambda _tab_id: None, gtk_module=_FallbackGtk)

    assert "tab-strip" in bar.widget.css_classes
    assert list(bar.buttons) == ["alerts", "codex", "claude"]
    assert bar.title_labels["alerts"].text == "⚠ Alerts"
    assert bar.title_labels["claude"].text == "Claude Code"

    assert "tab" in bar.buttons["alerts"].css_classes
    assert "active" in bar.buttons["codex"].css_classes
    assert "active" not in bar.buttons["alerts"].css_classes
    assert "active" not in bar.buttons["claude"].css_classes

    assert bar.badges["alerts"].text == "2"
    assert "tab-badge" in bar.badges["alerts"].css_classes
    assert "err" in bar.badges["alerts"].css_classes
    assert bar.badges["alerts"].visible is True

    assert bar.badges["codex"].text == "1"
    assert "warn" in bar.badges["codex"].css_classes

    assert bar.badges["claude"].visible is False
    assert "warn" not in bar.badges["claude"].css_classes
    assert "err" not in bar.badges["claude"].css_classes


def test_tab_click_fires_on_select_and_moves_active() -> None:
    selected: list[str] = []
    bar = TabBar(_tabs(), "codex", selected.append, gtk_module=_FallbackGtk)

    bar.buttons["claude"].emit("clicked")

    assert selected == ["claude"]
    assert bar.active == "claude"
    assert "active" in bar.buttons["claude"].css_classes
    assert "active" not in bar.buttons["codex"].css_classes


def test_set_active_updates_visuals_without_firing_on_select() -> None:
    selected: list[str] = []
    bar = TabBar(_tabs(), "codex", selected.append, gtk_module=_FallbackGtk)

    bar.set_active("alerts")

    assert selected == []
    assert bar.active == "alerts"
    assert "active" in bar.buttons["alerts"].css_classes
    assert "active" not in bar.buttons["codex"].css_classes


def test_update_same_tab_set_mutates_in_place_and_keeps_active() -> None:
    bar = TabBar(_tabs(), "codex", lambda _tab_id: None, gtk_module=_FallbackGtk)
    original_buttons = dict(bar.buttons)

    bar.update(
        (
            TabVM(id="alerts", label="⚠ Alerts", badge_count=0, badge_level=""),
            TabVM(id="codex", label="Codex", badge_count=3, badge_level="err"),
            TabVM(id="claude", label="Claude Code", badge_count=1, badge_level="warn"),
        )
    )

    for tab_id, button in original_buttons.items():
        assert bar.buttons[tab_id] is button
    assert bar.active == "codex"
    assert "active" in bar.buttons["codex"].css_classes

    assert bar.badges["alerts"].visible is False
    assert "err" not in bar.badges["alerts"].css_classes

    assert bar.badges["codex"].text == "3"
    assert "err" in bar.badges["codex"].css_classes
    assert "warn" not in bar.badges["codex"].css_classes

    assert bar.badges["claude"].visible is True
    assert bar.badges["claude"].text == "1"
    assert "warn" in bar.badges["claude"].css_classes


def test_update_with_changed_tab_set_rebuilds_and_keeps_active() -> None:
    bar = TabBar(_tabs(), "codex", lambda _tab_id: None, gtk_module=_FallbackGtk)

    bar.update(
        (
            *_tabs(),
            TabVM(id="grok", label="Grok", badge_count=0, badge_level=""),
        )
    )

    assert list(bar.buttons) == ["alerts", "codex", "claude", "grok"]
    assert bar.active == "codex"
    assert "active" in bar.buttons["codex"].css_classes
    assert bar.buttons["grok"] in bar.widget.children
