"""Drill screen — test your knowledge of an opening's moves."""

from __future__ import annotations

import chess
from rich.text import Text
from textual.app import ComposeResult
from textual.screen import Screen
from textual.reactive import reactive
from textual.widgets import Static, Footer, Header, Input
from textual.containers import Horizontal, Vertical
from textual.timer import Timer

from chess_cli.openings.models import Opening, OpeningNode, flatten_main_line
from chess_cli.tui.widgets.board import BoardWidget
from chess_cli.tui.widgets.explanation import ExplanationWidget
from chess_cli.tui.widgets.move_list import MoveListWidget


class DrillScreen(Screen):
    """Drill mode — enter the correct opening moves."""

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

#drill-top-info {
    height: 1;
    margin: 1 1 0 1;
    padding-left: 2;
}

#board-area {
    height: 1fr;
    min-height: 14;
    margin: 1 1;
}

#board {
    width: 28;
    height: 10;
}

#drill-panel {
    width: 1fr;
    min-width: 26;
    height: 100%;
    margin-left: 2;
    padding: 0 1;
}

#drill-panel-title {
    text-align: center;
    text-style: bold;
    color: $text-muted;
    width: 100%;
    height: 1;
    padding: 1 0 0 0;
}

#drill-feedback {
    width: 100%;
    height: 2;
    padding: 1 1;
}

#drill-stats {
    width: 100%;
    height: 1;
    padding: 0 1;
    color: $text-muted;
    margin-bottom: 1;
}

#move-list {
    width: 100%;
    height: 1fr;
    overflow-y: auto;
    border: round $primary-background;
}

#status-line {
    height: 1;
    margin: 1 2 0 2;
    color: $error;
}

#move-input {
    margin: 1 2 0 2;
}
"""

    BINDINGS = [
        ("escape", "back", "Back"),
    ]

    def __init__(self, opening: Opening) -> None:
        super().__init__()
        self.opening = opening
        self._board = chess.Board()
        self._san_history: list[str] = []
        self._move_history: list[chess.Move] = []
        self._main_line = flatten_main_line(opening)

        # Current position in the main line
        self._line_index = 0
        self._correct_count = 0
        self._total_attempts = 0
        self._completed = False

        # Track which side the player plays
        self._player_color = opening.color

    def compose(self) -> ComposeResult:
        yield Header(show_clock=False)
        yield Static("", id="drill-top-info")
        with Horizontal(id="board-area"):
            yield BoardWidget(id="board")
            with Vertical(id="drill-panel"):
                yield Static("Drill Mode", id="drill-panel-title")
                yield ExplanationWidget(id="explanation")
                yield Static("", id="drill-feedback")
                yield Static("", id="drill-stats")
                yield MoveListWidget(id="move-list")
        yield Static("", id="status-line")
        yield Input(placeholder="Enter the book move...", id="move-input")
        yield Footer()

    def on_mount(self) -> None:
        top_info = self.query_one("#drill-top-info", Static)
        color_icon = "\u265a" if self.opening.color == chess.WHITE else "\u2654"
        top_info.update(f"{color_icon} {self.opening.name} — Drill")

        board_widget = self.query_one("#board", BoardWidget)
        board_widget.perspective = self._player_color == chess.WHITE

        explanation = self.query_one("#explanation", ExplanationWidget)
        explanation.move_san = ""
        explanation.explanation = "Enter the first move of the opening."

        self._update_stats()
        self._update_display()

        # If player is Black, auto-play White's first move
        if self._player_color == chess.BLACK and self._line_index < len(self._main_line):
            self._auto_play_opponent()

        self.query_one("#move-input", Input).focus()

    def _is_player_move(self) -> bool:
        """Check if the current move in the line is the player's move."""
        return self._board.turn == self._player_color

    def _update_display(self) -> None:
        board_widget = self.query_one("#board", BoardWidget)
        board_widget.board_fen = self._board.fen()

        if self._move_history:
            last = self._move_history[-1]
            board_widget.highlight_from = last.from_square
            board_widget.highlight_to = last.to_square
        else:
            board_widget.highlight_from = -1
            board_widget.highlight_to = -1

        self.query_one("#move-list", MoveListWidget).update_moves(self._san_history)

    def _update_stats(self) -> None:
        stats = self.query_one("#drill-stats", Static)
        if self._total_attempts > 0:
            stats.update(f"  Correct: {self._correct_count}/{self._total_attempts}")
        else:
            stats.update("")

    def _set_feedback(self, msg: str, style: str = "") -> None:
        fb = self.query_one("#drill-feedback", Static)
        text = Text()
        text.append(f"  {msg}", style=style)
        fb.update(text)

    def _set_status(self, msg: str) -> None:
        self.query_one("#status-line", Static).update(f"  {msg}" if msg else "")

    def _auto_play_opponent(self) -> None:
        """Auto-play the opponent's move from the opening tree."""
        if self._line_index >= len(self._main_line):
            return

        san, explanation = self._main_line[self._line_index]
        move = self._board.parse_san(san)
        san_str = self._board.san(move)
        self._board.push(move)
        self._san_history.append(san_str)
        self._move_history.append(move)
        self._line_index += 1

        # Show opponent's move explanation
        expl_widget = self.query_one("#explanation", ExplanationWidget)
        expl_widget.move_san = san_str
        expl_widget.explanation = explanation if explanation else "(Opponent's move)"

        self._update_display()

    def on_input_submitted(self, event: Input.Submitted) -> None:
        user_input = event.value.strip()
        event.input.value = ""
        if not user_input:
            return

        cmd = user_input.lower()

        if cmd in ("quit", "q"):
            self.app.pop_screen()
            return
        elif cmd == "hint":
            if self._line_index < len(self._main_line):
                hint_san = self._main_line[self._line_index][0]
                self._set_feedback(f"Hint: the book move is {hint_san}", "yellow")
            return
        elif cmd == "restart":
            self._restart()
            return
        elif cmd in ("help", "h", "?"):
            self.notify(
                "Commands: hint, restart, quit\n"
                "Enter the correct book move in SAN notation.",
                title="Drill Help",
                timeout=10,
            )
            return

        if self._completed:
            self._set_status("Drill complete! Type 'restart' to try again or 'quit' to exit.")
            return

        self._try_move(user_input)

    def _try_move(self, user_input: str) -> None:
        if self._line_index >= len(self._main_line):
            return

        expected_san = self._main_line[self._line_index][0]
        expected_explanation = self._main_line[self._line_index][1]

        # Normalize castling
        move_input = user_input.replace("0-0-0", "O-O-O").replace("0-0", "O-O")

        # Try to parse
        try:
            move = self._board.parse_san(move_input)
            played_san = self._board.san(move)
        except (chess.InvalidMoveError, chess.IllegalMoveError, chess.AmbiguousMoveError):
            self._set_status(f"Invalid move: {user_input}")
            return

        self._set_status("")
        self._total_attempts += 1

        # Check against expected
        expected_move = self._board.parse_san(expected_san)
        if move == expected_move:
            # Correct!
            self._correct_count += 1
            self._board.push(move)
            self._san_history.append(played_san)
            self._move_history.append(move)
            self._line_index += 1

            expl_widget = self.query_one("#explanation", ExplanationWidget)
            expl_widget.move_san = played_san
            expl_widget.explanation = expected_explanation

            self._set_feedback("Correct!", "green bold")
            self._update_display()
            self._update_stats()

            # Check if we're done
            if self._line_index >= len(self._main_line):
                self._on_complete()
                return

            # Auto-play opponent response after a brief moment
            if not self._is_player_move():
                self.set_timer(0.5, self._delayed_opponent_play)
        else:
            # Wrong move
            self._set_feedback(f"Not the book move — try again.", "red")
            self._update_stats()

    def _delayed_opponent_play(self) -> None:
        """Called by timer to auto-play opponent's response."""
        if not self._completed and not self._is_player_move() and self._line_index < len(self._main_line):
            self._auto_play_opponent()
            # Check if drill is now complete after opponent played
            if self._line_index >= len(self._main_line):
                self._on_complete()

    def _on_complete(self) -> None:
        self._completed = True
        total = len([m for i, m in enumerate(self._main_line) if self._is_player_move_at(i)])
        self._set_feedback(
            f"Opening complete! {self._correct_count}/{self._total_attempts} correct.",
            "green bold",
        )
        inp = self.query_one("#move-input", Input)
        inp.placeholder = "Type 'restart' to drill again or 'quit' to exit..."

    def _is_player_move_at(self, index: int) -> bool:
        """Check if the move at the given index in the main line is the player's."""
        # Move 0 is White, 1 is Black, etc.
        move_color = chess.WHITE if index % 2 == 0 else chess.BLACK
        return move_color == self._player_color

    def _restart(self) -> None:
        self._board.reset()
        self._san_history.clear()
        self._move_history.clear()
        self._line_index = 0
        self._correct_count = 0
        self._total_attempts = 0
        self._completed = False

        self._set_feedback("")
        self._set_status("")
        self._update_stats()
        self._update_display()

        expl = self.query_one("#explanation", ExplanationWidget)
        expl.move_san = ""
        expl.explanation = "Enter the first move of the opening."

        inp = self.query_one("#move-input", Input)
        inp.placeholder = "Enter the book move..."
        inp.focus()

        # If player is Black, auto-play first move
        if self._player_color == chess.BLACK:
            self._auto_play_opponent()

    def action_back(self) -> None:
        self.app.pop_screen()
