"""Reusable upload widget for document submission."""

from __future__ import annotations

from collections.abc import Awaitable
from collections.abc import Callable

from nicegui import ui
from nicegui.binding import bindable_dataclass
from nicegui.events import UploadEventArguments

from transcription.errors import AppError
from transcription.services.documents import UploadJobResult
from transcription.ui.components.error_presenter import show_error
from transcription.ui.components.error_presenter import summarize_error
from transcription.worker import WorkerNotifier

type UploadSubmitter = Callable[[str, bytes], Awaitable[UploadJobResult]]


@bindable_dataclass
class UploadWidgetState:
    """Simple state container for upload feedback."""

    loading: bool = False
    message: str = ""


def render_upload_widget(*, submitter: UploadSubmitter, notifier: WorkerNotifier | None = None) -> None:
    """Render upload controls and common status/error handling."""
    state = UploadWidgetState()
    status_label = ui.label("Upload a document to start transcription.")
    status_label.bind_text(state, "message")

    async def on_upload(event: UploadEventArguments) -> None:
        if state.loading:
            ui.notify("Upload already in progress. Please wait.", type="warning")
            return

        state.loading = True
        status_label.text = "Uploading..."
        try:
            payload = await event.file.read()
            result = await submitter(event.file.name, payload)
            job_id = result.job_id
            state.message = f"Created job {job_id}" if job_id is not None else "Upload complete"
            status_label.text = state.message
            if notifier is not None:
                notifier.notify()
            ui.notify(state.message, type="positive")
        except AppError as exc:
            state.message = summarize_error(exc, operation="upload.submit")
            status_label.text = f"Upload failed: {state.message}"
            show_error(exc, title="Upload failed", operation="upload.submit")
        except Exception as exc:  # noqa: BLE001
            state.message = summarize_error(exc, operation="upload.submit")
            status_label.text = f"Upload failed: {state.message}"
            show_error(exc, title="Upload failed", operation="upload.submit")
        finally:
            state.loading = False

    ui.upload(
        on_upload=on_upload,
        auto_upload=True,
        label="Select document file",
    ).props('accept=".jpg,.jpeg,.png,.tif,.tiff,.pdf"')
