"""Interviews pane: DataTable of mock interviews with detail/feedback drill-down."""

from textual import work
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Vertical, VerticalScroll
from textual.widgets import DataTable, Static

from skilark_cli.tui.errors import friendly_error_message


def _status_label(status: str) -> str:
    """Return a Rich-markup-coloured status label."""
    styles: dict[str, str] = {
        "scheduled": "[cyan]scheduled[/cyan]",
        "in_progress": "[yellow]in_progress[/yellow]",
        "completed": "[green]completed[/green]",
        "cancelled": "[dim]cancelled[/dim]",
        "failed": "[red]failed[/red]",
    }
    return styles.get(status, status)


def _render_feedback(fb: dict) -> str:
    """Render feedback dict as Rich markup text for the detail view.

    Handles partial feedback (missing keys) gracefully.
    """
    lines: list[str] = []

    score = fb.get("overall_score")
    if score is not None:
        stars = "★" * int(score) + "☆" * (5 - int(score))
        lines.append(f"[bold]Overall Score:[/bold] {score}/5  {stars}")

    summary = fb.get("summary", "")
    if summary:
        lines.append(f"\n[bold]Summary[/bold]\n{summary}")

    strengths = fb.get("strengths") or []
    if strengths:
        lines.append("\n[bold green]Strengths[/bold green]")
        for s in strengths:
            lines.append(f"  [green]+[/green] {s}")

    improvements = fb.get("improvements") or []
    if improvements:
        lines.append("\n[bold yellow]Areas for Improvement[/bold yellow]")
        for imp in improvements:
            lines.append(f"  [yellow]-[/yellow] {imp}")

    question_scores = fb.get("question_scores") or []
    if question_scores:
        lines.append("\n[bold]Question Breakdown[/bold]")
        for qs in question_scores:
            question = qs.get("question", "")
            q_score = qs.get("score")
            notes = qs.get("notes", "")
            score_str = f"  [{q_score}/5]" if q_score is not None else ""
            lines.append(f"  [dim]Q:[/dim] {question}{score_str}")
            if notes:
                lines.append(f"    [dim]{notes}[/dim]")

    return "\n".join(lines)


class InterviewsPane(Vertical):
    """Interviews list with detail/feedback drill-down."""

    BINDINGS = [
        Binding("n", "new_interview", "Book", show=True),
        Binding("r", "refresh", "Refresh", show=True),
        Binding("f", "view_feedback", "View Detail", show=False),
        Binding("b", "back", "Back", show=False),
        Binding("escape", "back", "Back", show=False),
    ]

    def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None:
        """Handle Enter/click on a row — drill into detail/feedback."""
        self.action_view_feedback()

    def __init__(self, client=None, **kwargs) -> None:
        super().__init__(**kwargs)
        self.client = client
        self._interviews: list[dict] = []
        self._view: str = "list"

    def compose(self) -> ComposeResult:
        yield Static("", id="interviews-header")
        yield DataTable(id="interviews-table")
        yield VerticalScroll(
            Static("", id="interview-detail"),
            id="interview-detail-scroll",
        )

    def on_mount(self) -> None:
        table = self.query_one("#interviews-table", DataTable)
        table.cursor_type = "row"
        table.add_columns("Role", "Type", "Company", "When", "Status", "Feedback")

        # Detail scroll is hidden until user drills in.
        self.query_one("#interview-detail-scroll", VerticalScroll).display = False

        self._load_interviews()

    def activate(self) -> None:
        """Called when tab becomes active — reload data and restore footer."""
        self._load_interviews()
        self._update_footer_bindings()

    # ------------------------------------------------------------------
    # Data loading
    # ------------------------------------------------------------------

    @work(thread=True, exit_on_error=False)
    def _load_interviews(self) -> None:
        if not self.client:
            self.app.call_from_thread(
                self._render_empty, "No API client configured."
            )
            return
        try:
            data = self.client.list_interviews()
        except Exception as exc:
            self.app.call_from_thread(
                self._render_empty, friendly_error_message(exc)
            )
            return
        interviews = data.get("interviews", [])
        self.app.call_from_thread(self._render_interviews, interviews)

    def _render_interviews(self, interviews: list[dict]) -> None:
        if not self.is_attached:
            return
        self._interviews = interviews
        self._show_list_view()

    @work(thread=True, exit_on_error=False)
    def _load_detail(self, interview_id: str) -> None:
        """Load interview detail + feedback in the background, then render."""
        try:
            interview = self.client.get_interview(interview_id)
        except Exception as exc:
            self.app.call_from_thread(
                self._render_detail_error, friendly_error_message(exc)
            )
            return

        # has_feedback comes from the list endpoint (LEFT JOIN), not from
        # GetInterview. Look it up from the cached list data.
        list_entry = next((iv for iv in self._interviews if iv["id"] == interview_id), None)
        has_feedback = (list_entry or {}).get("has_feedback", False)

        feedback: dict | None = None
        if has_feedback:
            try:
                feedback = self.client.get_interview_feedback(interview_id)
            except Exception:
                # Feedback fetch failure is non-fatal — show interview without it.
                feedback = None

        # Carry has_feedback into the interview dict for rendering.
        interview["has_feedback"] = has_feedback
        self.app.call_from_thread(self._render_detail, interview, feedback)

    # ------------------------------------------------------------------
    # Rendering
    # ------------------------------------------------------------------

    def _render_empty(self, message: str) -> None:
        if not self.is_attached:
            return
        self.query_one("#interviews-header", Static).update(
            f"[bold]Interviews[/bold]\n\n[dim]{message}[/dim]"
        )

    def _render_interviews_table(self) -> None:
        """Populate the DataTable from self._interviews."""
        header = self.query_one("#interviews-header", Static)
        if not self._interviews:
            header.update(
                "[bold]Interviews[/bold]\n\n"
                "[dim]No interviews scheduled. Press [bold]n[/bold] to book one.[/dim]"
            )
        else:
            count = len(self._interviews)
            header.update(
                f"[bold]Interviews[/bold]  "
                f"({count} interview{'s' if count != 1 else ''})"
            )

        table = self.query_one("#interviews-table", DataTable)
        table.clear()
        for iv in self._interviews:
            role = iv.get("role_title", "")
            iv_type = iv.get("interview_type", "")
            company = iv.get("company_slug", "") or "-"
            scheduled_at = iv.get("scheduled_at", "")
            when = scheduled_at[:10] if scheduled_at else "-"
            status = _status_label(iv.get("status", ""))
            feedback_flag = "[green]✓[/green]" if iv.get("has_feedback") else "-"
            table.add_row(
                role, iv_type, company, when, status, feedback_flag,
                key=iv["id"],
            )

    def _render_detail(self, interview: dict, feedback: dict | None) -> None:
        """Render the detail panel for a single interview."""
        if not self.is_attached:
            return

        role = interview.get("role_title", "")
        iv_type = interview.get("interview_type", "")
        company = interview.get("company_slug", "") or "-"
        status = interview.get("status", "")
        scheduled_at = interview.get("scheduled_at", "")
        when = scheduled_at[:10] if scheduled_at else "-"

        lines: list[str] = [
            f"[bold]{role}[/bold]  [dim]({iv_type})[/dim]",
            f"[dim]Company:[/dim] {company}   "
            f"[dim]Date:[/dim] {when}   "
            f"[dim]Status:[/dim] {_status_label(status)}",
        ]

        transcript = interview.get("transcript") or []
        if transcript:
            lines.append("\n[bold]Transcript[/bold]")
            for turn in transcript[:20]:  # cap to avoid overwhelming the view
                speaker = turn.get("speaker", "")
                text = turn.get("text", "")
                prefix = "[bold cyan]Bot:[/bold cyan]" if speaker == "bot" else "[bold]You:[/bold]"
                lines.append(f"  {prefix} {text}")
            if len(transcript) > 20:
                lines.append(f"  [dim]... {len(transcript) - 20} more turns[/dim]")

        if feedback:
            lines.append("\n" + "─" * 40)
            lines.append("[bold]AI Feedback[/bold]")
            lines.append(_render_feedback(feedback))
        elif interview.get("has_feedback"):
            lines.append("\n[dim]Loading feedback...[/dim]")
        elif status == "completed":
            lines.append("\n[dim]Feedback not yet generated.[/dim]")

        detail = self.query_one("#interview-detail", Static)
        detail.update("\n".join(lines))

        header = self.query_one("#interviews-header", Static)
        header.update(
            f"[bold]{role}[/bold]  [dim](press [bold]b[/bold] or Esc to go back)[/dim]"
        )

    def _render_detail_error(self, message: str) -> None:
        if not self.is_attached:
            return
        detail = self.query_one("#interview-detail", Static)
        detail.update(f"[red]{message}[/red]")

    # ------------------------------------------------------------------
    # View switching
    # ------------------------------------------------------------------

    def _show_list_view(self) -> None:
        self._view = "list"
        self._render_interviews_table()
        self.query_one("#interviews-table", DataTable).display = True
        self.query_one("#interview-detail-scroll", VerticalScroll).display = False
        self._update_footer_bindings()

    def _show_detail_view(self, interview_id: str) -> None:
        self._view = "detail"
        self.query_one("#interviews-table", DataTable).display = False
        self.query_one("#interview-detail-scroll", VerticalScroll).display = True
        # Clear the detail while loading.
        self.query_one("#interview-detail", Static).update("[dim]Loading...[/dim]")
        self._update_footer_bindings()
        self._load_detail(interview_id)

    def _update_footer_bindings(self) -> None:
        """Push view-aware bindings to the footer."""
        from skilark_cli.tui.app import FooterBar

        try:
            footer = self.app.query_one(FooterBar)
        except Exception:
            return

        if self._view == "list":
            bindings = [
                Binding("n", "new_interview", "Book", show=True),
                Binding("r", "refresh", "Refresh", show=True),
                Binding("f", "view_feedback", "View Detail", show=True),
            ]
        else:
            bindings = [
                Binding("b", "back", "Back", show=True),
            ]
        footer.set_context_bindings(bindings)

    # ------------------------------------------------------------------
    # Actions
    # ------------------------------------------------------------------

    def action_refresh(self) -> None:
        """Reload the interviews list."""
        if self._view != "list":
            return
        self.query_one("#interviews-header", Static).update(
            "[bold]Interviews[/bold]\n\n[dim]Loading...[/dim]"
        )
        self._load_interviews()

    def action_view_feedback(self) -> None:
        """Drill into detail/feedback for the selected row."""
        if self._view != "list":
            return
        table = self.query_one("#interviews-table", DataTable)
        if table.cursor_row is None or not self._interviews:
            return
        # Use the DataTable row key (set to interview ID during add_row) to
        # look up the interview — this is safe even if rows get reordered.
        try:
            row_key = table.coordinate_to_cell_key(table.cursor_coordinate).row_key
            interview_id = str(row_key.value)
        except Exception:
            # Fallback to cursor index if key lookup fails.
            idx = table.cursor_row
            if not (0 <= idx < len(self._interviews)):
                return
            interview_id = self._interviews[idx]["id"]

        self._show_detail_view(interview_id)

    def action_new_interview(self) -> None:
        """Open the booking modal."""
        if self._view != "list":
            return
        from skilark_cli.tui.screens.interview_book_modal import InterviewBookModal

        def _on_dismiss(result: bool | None) -> None:
            if result:
                self._load_interviews()

        self.app.push_screen(InterviewBookModal(client=self.client), _on_dismiss)

    def action_back(self) -> None:
        """Return from detail view to the list."""
        if self._view == "detail":
            self._show_list_view()
