"""Schema update modal for editing existing schemas.

Provides a modal screen that allows users to edit schema name and description.
"""

import re
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

from textual import on, work
from textual.app import ComposeResult
from textual.containers import Horizontal, VerticalScroll
from textual.widgets import (
    Button,
    Input,
    Label,
    Static,
)

from cli.tui.widgets.base_form_modal import BaseFormModal

from alloy_runtime_sdk.api_client.client import ApiClient
from alloy_runtime_types.dtos.schemas import GetSchemaResponse, UpdateSchemaRequest

if TYPE_CHECKING:
    from cli.tui.app import AlloyRuntimeApp


@dataclass
class SchemaUpdateResult:
    """Result of successful schema update."""

    schema_id: str
    schema_name: str
    version: int


class SchemaUpdateModal(BaseFormModal[SchemaUpdateResult]):
    """Modal for updating schema name and description.

    Usage:
        def on_schema_updated(result: SchemaUpdateResult | None):
            if result is not None:
                self.notify(f"Updated schema: {result.schema_name}")
                self._do_search("")  # Refresh list

        client = await self.app.store.get_client()
        full_schema = await client.get_schema(schema_id)
        self.app.push_screen(
            SchemaUpdateModal(client=client, schema=full_schema),
            on_schema_updated
        )
    """

    app: "AlloyRuntimeApp"

    def __init__(
        self,
        client: ApiClient,
        schema: GetSchemaResponse,
        **kwargs: Any,
    ) -> None:
        """Initialize the schema update modal.

        Args:
            client: ApiClient instance for API calls
            schema: The schema to edit (full details from get_schema)
        """
        super().__init__(**kwargs)
        self._client = client
        self._schema = schema

    def compose(self) -> ComposeResult:
        with VerticalScroll(id="schema-update-modal"):
            yield Label(
                f"Edit Schema: {self._schema.schema_name}", classes="modal-title"
            )

            # Schema info (read-only)
            yield Static("[bold]Schema Info[/]", classes="form-section")

            yield Static(
                f"[dim]Format:[/] {self._schema.schema_format_id}  "
                f"[dim]Version:[/] v{self._schema.version}  "
                f"[dim]ID:[/] {self._schema.id}",
                id="schema-info",
                classes="info-display",
            )

            # Editable fields
            yield Static("[bold]Edit Properties[/]", classes="form-section")

            yield Static(
                "Name (lowercase, dots/dashes/underscores)", classes="field-label"
            )
            yield Input(
                value=self._schema.schema_name,
                placeholder="e.g., user.profile, api.response-format",
                id="name-input",
            )

            yield Static("Description", classes="field-label")
            yield Input(
                value=self._schema.description or "",
                placeholder="Brief description of this schema's purpose",
                id="description-input",
            )

            # Error display
            yield Static("", id="error-display", classes="error-display")

            with Horizontal(classes="button-row"):
                yield Button("Update Schema", id="update-btn", variant="success")
                yield Button("Cancel", id="cancel-btn", variant="default")

    def on_mount(self) -> None:
        """Focus the name input on mount."""
        self.query_one("#name-input", Input).focus()

    @on(Button.Pressed, "#update-btn")
    def on_update_pressed(self, event: Button.Pressed) -> None:
        """Handle update button press."""
        self.action_submit()

    @on(Button.Pressed, "#cancel-btn")
    def on_cancel_pressed(self, event: Button.Pressed) -> None:
        """Handle cancel button press."""
        self.dismiss(None)

    def action_submit(self) -> None:
        """Handle form submission."""
        try:
            self._validate_fields()
            self._hide_error()
            self._finalize_submission()
        except ValueError as e:
            self._show_error(str(e))

    def _validate_fields(self) -> None:
        """Validate all required fields."""
        name = self.query_one("#name-input", Input).value.strip()
        if not name:
            raise ValueError("Name is required")

        if not re.match(r"^[a-z0-9._-]+$", name):
            raise ValueError(
                "Name must be lowercase alphanumeric with dots, dashes, or underscores only"
            )

    def _build_request(self) -> UpdateSchemaRequest:
        """Build the API request."""
        name = self.query_one("#name-input", Input).value.strip()
        description = self.query_one("#description-input", Input).value.strip()

        # Only include fields that have changed
        request_name = name if name != self._schema.schema_name else None
        request_description = (
            description if description != (self._schema.description or "") else None
        )

        return UpdateSchemaRequest(
            name=request_name,
            description=request_description,
        )

    @work(exclusive=True)
    async def _finalize_submission(self) -> None:
        """Submit to API."""
        try:
            request = self._build_request()

            # Check if anything actually changed
            if request.name is None and request.description is None:
                self.app.notify("No changes made", severity="information")
                self.dismiss(None)
                return

            response = await self._client.update_schema(self._schema.id, request)

            result = SchemaUpdateResult(
                schema_id=str(response.id),
                schema_name=response.schema_name,
                version=response.version,
            )
            self.dismiss(result)

        except Exception as e:
            self._show_error(f"Failed to update schema: {e}")
