"""Reusable transcript UI components."""

from __future__ import annotations

from collections.abc import Awaitable
from collections.abc import Callable
from datetime import datetime
from typing import Any

from nicegui import ui

from transcription.db.models import Job
from transcription.db.models import JobSource
from transcription.db.models import Source

type RevisionAction = Callable[[Source], Awaitable[None] | None]


def render_original_transcription_card(*, job: Job, classes: str = "w-full") -> Any:
    """Render the immutable original job transcription output."""
    latest_error_detail = _latest_job_error_detail(job)
    status_label = "Failed" if latest_error_detail else "Transcribed"
    header = f"Original Transcription | {status_label}"
    provider = job.provider or "unknown"
    model = job.model or "unknown"
    caption = f"{provider} | {model} | {_format_created_at(job.date_updated)}"

    card = ui.card().classes(f"{classes} q-pa-md vibe-card")
    with card, ui.column().classes("w-full q-gutter-y-sm"):
        ui.label(header).classes("text-subtitle1 text-weight-medium")
        ui.label(caption).classes("text-caption vibe-text-muted")
        _metadata_row(label="Prompt", value=job.prompt_name or "unknown")
        _metadata_row(label="Updated", value=_format_created_at(job.date_updated))

        latest_transcription = _latest_job_transcription(job)

        if latest_transcription:
            with ui.card().classes("w-full q-pa-sm"):
                ui.markdown(latest_transcription)

        if latest_error_detail:
            with ui.card().classes("w-full vibe-card--error q-pa-sm"):
                ui.label("Failure detail").classes("text-caption text-uppercase")
                ui.label(latest_error_detail).classes("text-body2")

    return card


def render_revision_row(
    *,
    revision: Source | None,
    initially_expanded: bool = False,
    classes: str = "w-full",
    on_delete: RevisionAction | None = None,
) -> Any:
    """Render a collapsible row for the single optional source revision."""
    if revision is None:
        return None

    header = "Source revision | User-authored"
    caption = _format_created_at(revision.date_revised or revision.date_uploaded)

    expansion = ui.expansion(value=initially_expanded, group="group").classes(f"{classes} rounded-borders vibe-card")

    with expansion, ui.column().classes("w-full q-gutter-y-sm q-pa-sm"):
        with expansion.add_slot("header"), ui.row().classes("w-full items-start justify-between q-gutter-md"):
            with ui.column().classes("q-gutter-none"):
                ui.label(header).classes("text-subtitle1 text-weight-medium")
                ui.label(caption).classes("text-caption vibe-text-muted")

            if on_delete is not None:
                with ui.dialog() as delete_dialog, ui.card().classes("q-pa-md"):
                    ui.label("Delete this source revision?").classes("text-body1")
                    with ui.row().classes("w-full justify-end q-gutter-sm"):
                        ui.button("Cancel", on_click=lambda: delete_dialog.submit(False)).props("flat")
                        ui.button("Delete", on_click=lambda: delete_dialog.submit(True)).props(
                            'unelevated color="negative"'
                        )

                async def delete_current_transcript() -> None:
                    delete_dialog.open()
                    confirmed = await delete_dialog
                    if not confirmed:
                        return

                    maybe_awaitable = on_delete(revision)
                    if isinstance(maybe_awaitable, Awaitable):
                        await maybe_awaitable

                with ui.column(align_items="center").classes("self-center q-gutter-none"):
                    ui.button(icon="delete", on_click=delete_current_transcript).props(
                        'flat round dense color="negative"'
                    )
        _metadata_row(label="Created", value=_format_created_at(revision.date_revised or revision.date_uploaded))

        if revision.revised_text:
            with ui.card().classes("w-full q-pa-sm"):
                ui.markdown(revision.revised_text)

    return expansion


def _latest_job_transcription(job: Job) -> str | None:
    for job_source in sorted(job.job_sources, key=lambda item: item.executed_at, reverse=True):
        if job_source.raw_transcription:
            return job_source.raw_transcription
    return None


def _latest_job_error_detail(job: Job) -> str | None:
    for job_source in sorted(job.job_sources, key=lambda item: item.executed_at, reverse=True):
        if job_source.error_detail:
            return job_source.error_detail
    return None


def _format_created_at(value: datetime) -> str:
    """Return a compact UTC-like timestamp for row captions."""
    return value.strftime("%Y-%m-%d %H:%M:%S %Z")


def _metadata_row(*, label: str, value: str) -> None:
    with ui.row().classes("w-md items-start justify-between q-gutter-x-md"):
        ui.label(label).classes("text-caption vibe-text-muted text-uppercase")
        ui.label(value).classes("text-body2 text-right break-all")
