"""Jobs list and detail page registration."""

from __future__ import annotations

from dataclasses import dataclass
from uuid import UUID

from nicegui import ui
from sqlmodel import select

from transcription.db import get_session
from transcription.models import Document, Job, Transcript
from transcription.services.library import (
    accept_revision,
    add_revision,
    export_transcripts,
    list_revisions,
    search_accepted_transcripts,
)
from transcription.ui.error_presenter import show_error, summarize_error


@dataclass(frozen=True)
class JobView:
    """Read model for rendering job rows in the UI."""

    id: UUID
    status: str
    created_at: str
    updated_at: str


def fetch_jobs() -> list[JobView]:
    """Return jobs for display in most-recent-first order."""
    with get_session() as session:
        jobs = session.exec(select(Job).order_by(Job.created_at.desc())).all()
        return [
            JobView(
                id=job.id,
                status=job.status.value,
                created_at=job.created_at.isoformat(),
                updated_at=job.updated_at.isoformat(),
            )
            for job in jobs
        ]


def fetch_job_detail(job_id: UUID) -> tuple[Job | None, Document | None, Transcript | None]:
    """Return job, document, and transcript for detail view."""
    with get_session() as session:
        job = session.get(Job, job_id)
        if job is None:
            return None, None, None
        document = session.get(Document, job.document_id)
        transcript = session.exec(select(Transcript).where(Transcript.job_id == job.id)).first()
        return job, document, transcript


def register_page() -> None:
    """Register jobs list and detail routes."""

    @ui.page("/jobs")
    def jobs_page() -> None:
        ui.label("Transcription Jobs")
        status = ui.label("Ready")
        table_container = ui.column()

        def render_table() -> None:
            table_container.clear()
            jobs = fetch_jobs()
            with table_container:
                if not jobs:
                    ui.label("No jobs yet.")
                    return
                rows = [
                    {
                        "id": str(job.id),
                        "status": job.status,
                        "created_at": job.created_at,
                        "updated_at": job.updated_at,
                    }
                    for job in jobs
                ]
                ui.table(
                    columns=[
                        {"name": "id", "label": "Job ID", "field": "id"},
                        {"name": "status", "label": "Status", "field": "status"},
                        {"name": "created_at", "label": "Created", "field": "created_at"},
                        {"name": "updated_at", "label": "Updated", "field": "updated_at"},
                    ],
                    rows=rows,
                    row_key="id",
                )
                for row in rows:
                    ui.link(f"Open {row['id']}", f"/jobs/{row['id']}")

        def refresh() -> None:
            status.text = "Refreshing..."
            try:
                render_table()
                status.text = "Refreshed"
            except Exception as exc:  # noqa: BLE001
                status.text = f"Refresh failed: {summarize_error(exc, operation='jobs.refresh')}"
                show_error(exc, title="Jobs refresh failed", operation="jobs.refresh")

        ui.button("Refresh", on_click=refresh)
        render_table()
        ui.link("Back to upload", "/")

    @ui.page("/jobs/{job_id}")
    def job_detail_page(job_id: str) -> None:
        ui.label("Job Detail")
        try:
            parsed_id = UUID(job_id)
        except ValueError:
            ui.label("Invalid job id")
            ui.link("Back to jobs", "/jobs")
            return

        job, document, transcript = fetch_job_detail(parsed_id)
        if job is None:
            ui.label("Job not found")
            ui.link("Back to jobs", "/jobs")
            return

        ui.label(f"Job ID: {job.id}")
        ui.label(f"Status: {job.status.value}")
        ui.label(f"Created: {job.created_at.isoformat()}")
        ui.label(f"Updated: {job.updated_at.isoformat()}")

        if document is not None:
            ui.label(f"Filename: {document.filename}")
            ui.label(f"File path: {document.file_path}")

        if transcript is None:
            ui.label("Transcript not available yet.")
        elif transcript.text:
            ui.label("Transcript:")
            ui.markdown(transcript.text)
        elif transcript.error_detail:
            ui.label("Failure detail:")
            ui.label(transcript.error_detail)

        ui.separator()
        ui.label("Revision History")
        revisions_container = ui.column()

        def render_revisions() -> None:
            revisions_container.clear()
            with revisions_container:
                revisions = list_revisions(job_id=parsed_id)
                if not revisions:
                    ui.label("No revisions yet.")
                    return

                for revision in revisions:
                    with ui.card().classes("w-full"):
                        ui.label(
                            f"Revision {revision.revision_number} | source={revision.source} | accepted={revision.accepted}"
                        )
                        ui.markdown(revision.text)

                        if not revision.accepted:
                            ui.button(
                                "Accept revision",
                                on_click=lambda rev_id=revision.id: _accept_revision(rev_id),
                            )

        def _accept_revision(revision_id):
            try:
                accept_revision(revision_id=revision_id)
                ui.notify("Revision accepted", type="positive")
                render_revisions()
            except Exception as exc:  # noqa: BLE001
                show_error(exc, title="Accept revision failed", operation="revisions.accept")

        new_revision_text = ui.textarea("Add revision text").props("rows=6")

        def _submit_revision() -> None:
            try:
                add_revision(job_id=parsed_id, text=new_revision_text.value or "", source="user", accepted=False)
                new_revision_text.value = ""
                ui.notify("Revision added", type="positive")
                render_revisions()
            except Exception as exc:  # noqa: BLE001
                show_error(exc, title="Add revision failed", operation="revisions.create")

        ui.button("Add revision", on_click=_submit_revision)

        render_revisions()

        ui.link("Search transcripts", "/search")
        ui.link("Export transcripts", "/export")
        ui.link("Back to jobs", "/jobs")

    @ui.page("/search")
    def search_page() -> None:
        ui.label("Search Accepted Transcripts")
        query_input = ui.input("Search query")
        results_container = ui.column()

        def run_search() -> None:
            results_container.clear()
            try:
                results = search_accepted_transcripts(query=query_input.value or "")
            except Exception as exc:  # noqa: BLE001
                show_error(exc, title="Search failed", operation="search.run")
                return

            with results_container:
                if not results:
                    ui.label("No results.")
                    return

                for result in results:
                    with ui.card().classes("w-full"):
                        ui.label(f"Job {result.job_id} | Revision {result.revision_number}")
                        ui.markdown(result.text)

        ui.button("Search", on_click=run_search)
        ui.link("Back to jobs", "/jobs")

    @ui.page("/export")
    def export_page() -> None:
        ui.label("Export Accepted Transcripts")
        results_container = ui.column()

        def run_export() -> None:
            results_container.clear()
            try:
                records = export_transcripts(accepted_only=True)
            except Exception as exc:  # noqa: BLE001
                show_error(exc, title="Export failed", operation="export.run")
                return

            with results_container:
                ui.label(f"Exported records: {len(records)}")
                for record in records:
                    with ui.card().classes("w-full"):
                        ui.label(f"{record['filename']} | Revision {record['revision_number']}")
                        ui.markdown(str(record["text"]))

        ui.button("Run export", on_click=run_export)
        ui.link("Back to jobs", "/jobs")
