"""Kanban TUI widgets - Card, Column, Board."""

from textual.app import ComposeResult
from textual.widget import Widget
from textual.widgets import Static, Label
from textual.containers import Vertical, VerticalScroll
from textual.reactive import reactive
from textual.message import Message

from .models import Task, ColumnId, AIStatus, COLUMN_CONFIG


class TaskCard(Widget):
    """A task card widget with real-time status updates."""

    DEFAULT_CSS = """
    TaskCard {
        height: auto;
        min-height: 3;
        max-height: 8;
        margin: 0 0 1 0;
        padding: 0 1;
        border: round #444444;
        background: #1a1a1a;
    }

    TaskCard:focus {
        border: round #61afef;
        background: #252525;
    }

    TaskCard.running {
        border: round #98c379;
    }

    TaskCard.failed {
        border: round #e06c75;
    }

    TaskCard.complete {
        border: round #56b6c2;
    }

    TaskCard .card-title {
        text-style: bold;
        color: #e8e8e8;
    }

    TaskCard .card-desc {
        color: #888888;
    }

    TaskCard .card-status {
        color: #61afef;
        text-style: italic;
    }

    TaskCard .card-status-complete {
        color: #98c379;
    }

    TaskCard .card-status-failed {
        color: #e06c75;
    }
    """

    # Spinner frames for animation
    SPINNERS = ["\u25d0", "\u25d3", "\u25d1", "\u25d2"]

    # Status display labels
    STATUS_LABELS = {
        AIStatus.IDLE: "",
        AIStatus.QUEUED: "Queued",
        AIStatus.PLANNING: "Planning",
        AIStatus.IMPLEMENTING: "Implementing",
        AIStatus.REVIEWING: "Reviewing",
        AIStatus.COMPLETE: "Complete",
        AIStatus.FAILED: "Failed",
    }

    can_focus = True
    task_id: reactive[str] = reactive("")
    _frame: reactive[int] = reactive(0)

    class Selected(Message):
        """Message sent when card is selected."""

        def __init__(self, task_id: str) -> None:
            self.task_id = task_id
            super().__init__()

    class Action(Message):
        """Message sent when action requested on card."""

        def __init__(self, task_id: str, action: str) -> None:
            self.task_id = task_id
            self.action = action
            super().__init__()

    def __init__(self, task: Task, **kwargs) -> None:
        super().__init__(**kwargs)
        self._task = task
        self.task_id = task.id
        self._update_classes()

    @property
    def task(self) -> Task:
        return self._task

    def update_task(self, task: Task) -> None:
        """Update the task data and refresh display."""
        self._task = task
        self._update_classes()
        self.refresh()

    def _update_classes(self) -> None:
        """Update CSS classes based on task status."""
        self.remove_class("running", "failed", "complete")
        if self._task.ai_status in (
            AIStatus.PLANNING,
            AIStatus.IMPLEMENTING,
            AIStatus.REVIEWING,
        ):
            self.add_class("running")
        elif self._task.ai_status == AIStatus.FAILED:
            self.add_class("failed")
        elif self._task.ai_status == AIStatus.COMPLETE:
            self.add_class("complete")

    def compose(self) -> ComposeResult:
        yield Static(self._task.title, classes="card-title")
        if self._task.description:
            desc = self._task.description[:40]
            if len(self._task.description) > 40:
                desc += "..."
            yield Static(desc, classes="card-desc")
        yield Static("", classes="card-status", id="status")

    def on_mount(self) -> None:
        """Start animation timer if task is active."""
        self._update_status()
        if self._is_active():
            self.set_interval(0.2, self._animate)

    def _is_active(self) -> bool:
        """Check if task is actively running."""
        return self._task.ai_status in (
            AIStatus.QUEUED,
            AIStatus.PLANNING,
            AIStatus.IMPLEMENTING,
            AIStatus.REVIEWING,
        )

    def _animate(self) -> None:
        """Animate the spinner."""
        if self._is_active():
            self._frame = (self._frame + 1) % len(self.SPINNERS)
            self._update_status()

    def _update_status(self) -> None:
        """Update the status line."""
        try:
            status_widget = self.query_one("#status", Static)
        except Exception:
            return

        status = self._task.ai_status

        if status == AIStatus.IDLE:
            status_widget.update("")
            status_widget.remove_class("card-status-complete", "card-status-failed")
            return

        if status == AIStatus.COMPLETE:
            files = len(self._task.files_modified)
            text = f"\u2713 {files} file{'s' if files != 1 else ''} modified"
            status_widget.update(text)
            status_widget.add_class("card-status-complete")
            return

        if status == AIStatus.FAILED:
            error = self._task.error or "Failed"
            status_widget.update(f"\u2717 {error[:30]}")
            status_widget.add_class("card-status-failed")
            return

        # Active status with spinner
        spinner = self.SPINNERS[self._frame]
        label = self.STATUS_LABELS.get(status, "")
        activity = self._task.current_activity
        if activity:
            activity = activity[:25]
            text = f"{spinner} {label}: {activity}"
        else:
            text = f"{spinner} {label}..."
        status_widget.update(text)

    def on_focus(self) -> None:
        """Notify when focused."""
        self.post_message(self.Selected(self.task_id))

    def on_click(self) -> None:
        """Focus on click."""
        self.focus()


class KanbanColumn(Widget):
    """A single column containing task cards."""

    DEFAULT_CSS = """
    KanbanColumn {
        width: 1fr;
        height: 100%;
        border: solid #333333;
        margin: 0 1 0 0;
    }

    KanbanColumn:focus-within {
        border: solid #61afef;
    }

    KanbanColumn .column-header {
        background: #2a2a2a;
        color: #e8e8e8;
        text-align: center;
        padding: 0 1;
        text-style: bold;
        height: 1;
    }

    KanbanColumn .column-count {
        color: #666666;
    }

    KanbanColumn .task-list {
        height: 1fr;
        padding: 1;
    }

    KanbanColumn .empty-message {
        color: #555555;
        text-align: center;
        padding: 2;
    }
    """

    def __init__(self, column_id: ColumnId, tasks: list[Task], **kwargs) -> None:
        super().__init__(**kwargs)
        self.column_id = column_id
        self._tasks = tasks
        self._config = COLUMN_CONFIG[column_id]

    def compose(self) -> ComposeResult:
        icon = self._config["icon"]
        title = self._config["title"]
        count = len(self._tasks)
        header_text = f"{icon} {title} ({count})"
        yield Static(header_text, classes="column-header")

        with VerticalScroll(classes="task-list"):
            if not self._tasks:
                yield Static("No tasks", classes="empty-message")
            else:
                for task in self._tasks:
                    yield TaskCard(task, id=f"card-{task.id}")

    def update_tasks(self, tasks: list[Task]) -> None:
        """Update the tasks in this column."""
        self._tasks = tasks
        # Update header count
        try:
            header = self.query_one(".column-header", Static)
            icon = self._config["icon"]
            title = self._config["title"]
            header.update(f"{icon} {title} ({len(tasks)})")
        except Exception:
            pass

    def get_card_ids(self) -> list[str]:
        """Get IDs of all cards in this column."""
        return [task.id for task in self._tasks]


class KanbanBoard(Widget):
    """Container for all columns."""

    DEFAULT_CSS = """
    KanbanBoard {
        layout: horizontal;
        width: 100%;
        height: 1fr;
        padding: 1;
    }
    """

    def __init__(self, state, **kwargs) -> None:
        super().__init__(**kwargs)
        self._state = state

    def compose(self) -> ComposeResult:
        for column_id in self._state.board.column_order:
            tasks = self._state.get_tasks_by_column(column_id)
            yield KanbanColumn(column_id, tasks, id=f"column-{column_id.value}")

    def refresh_column(self, column_id: ColumnId) -> None:
        """Refresh a specific column."""
        try:
            column = self.query_one(f"#column-{column_id.value}", KanbanColumn)
            tasks = self._state.get_tasks_by_column(column_id)
            column.update_tasks(tasks)
        except Exception:
            pass

    def refresh_all(self) -> None:
        """Refresh all columns."""
        for column_id in self._state.board.column_order:
            self.refresh_column(column_id)
