"""Schema creation modal for creating new validation schemas.

Provides a comprehensive modal screen that allows users to create a new schema
with support for JSON Schema or Regex formats, including JSON example generation.
"""

import json
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, Vertical, VerticalScroll
from textual.widgets import (
    Button,
    Input,
    Label,
    RadioButton,
    RadioSet,
    Static,
    TextArea,
)

from cli.infrastructure.scope_utils import get_scope_from_radioset
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 CreateSchemaRequest
from alloy_runtime_types.enums.ownership_scope import OwnershipScope
from alloy_runtime_types.enums.schema_enums import SchemaFormat

from cli.infrastructure.forms.json_schema_builder import JsonSchemaBuilder

if TYPE_CHECKING:
    from cli.tui.app import AlloyRuntimeApp


@dataclass
class SchemaCreateResult:
    """Result of successful schema creation."""

    schema_id: str
    schema_name: str
    version: int


class SchemaCreateModal(BaseFormModal[SchemaCreateResult]):
    """Modal for creating a new schema.

    Provides a comprehensive form with:
    - Required fields: name, schema format, definition
    - Schema definition via TextArea (paste JSON schema or regex)
    - JSON Schema generation from JSON example
    - Optional fields: description
    - Scope selection (user/organization/global)

    Usage:
        def on_schema_created(result: SchemaCreateResult | None):
            if result is not None:
                # Schema was created successfully
                self.notify(f"Created schema: {result.schema_name}")
                self._do_search("")  # Refresh list

        client = await self.app.store.get_client()
        self.app.push_screen(
            SchemaCreateModal(client=client),
            on_schema_created
        )
    """

    app: "AlloyRuntimeApp"

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

        Args:
            client: ApiClient instance for API calls
        """
        super().__init__(**kwargs)
        self._client = client

    def compose(self) -> ComposeResult:
        with VerticalScroll(id="schema-create-modal"):
            yield Label("Create New Schema", classes="modal-title")

            # ===== REQUIRED FIELDS =====
            yield Static("[bold]Required[/]", classes="form-section")

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

            yield Static("Schema Format", classes="field-label")
            with RadioSet(id="format-radios"):
                yield RadioButton("JSON Schema", id="format-json-schema", value=True)
                yield RadioButton("Regex", id="format-regex")

            yield Static("Scope", classes="field-label")
            with RadioSet(id="scope-radios"):
                yield RadioButton("User (personal)", id="scope-user")
                yield RadioButton("Organization", id="scope-org", value=True)
                yield RadioButton("Global", id="scope-global")

            # ===== SCHEMA DEFINITION =====
            yield Static("[bold]Schema Definition[/]", classes="form-section")

            yield Static(
                "Definition (paste JSON Schema or Regex pattern)", classes="field-label"
            )
            yield TextArea(
                id="definition-textarea",
                classes="definition-input",
            )

            # JSON Schema builder section (only visible for JSON Schema format)
            with Vertical(id="json-builder-section"):
                yield Static(
                    "Or: Generate from JSON example (JSON Schema only)",
                    classes="field-label",
                )
                yield JsonSchemaBuilder(id="schema-builder")
                yield Button(
                    "Use Generated Schema",
                    id="use-generated-btn",
                    variant="primary",
                    disabled=True,
                )

            # ===== OPTIONAL FIELDS =====
            yield Static("[bold]Optional[/]", classes="form-section")

            yield Static("Description", classes="field-label")
            yield Input(
                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("Create Schema", id="create-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(RadioSet.Changed, "#format-radios")
    def on_format_changed(self, event: RadioSet.Changed) -> None:
        """Handle schema format change - show/hide JSON builder."""
        json_builder_section = self.query_one("#json-builder-section", Vertical)
        if event.pressed.id == "format-json-schema":
            json_builder_section.display = True
        else:
            json_builder_section.display = False
            # Clear the builder when switching to regex
            self.query_one("#schema-builder", JsonSchemaBuilder).clear()

    @on(JsonSchemaBuilder.SchemaChanged)
    def on_schema_builder_changed(self, event: JsonSchemaBuilder.SchemaChanged) -> None:
        """Enable/disable the 'Use Generated Schema' button based on builder state."""
        use_btn = self.query_one("#use-generated-btn", Button)
        use_btn.disabled = event.schema is None

    @on(Button.Pressed, "#use-generated-btn")
    def on_use_generated_pressed(self, event: Button.Pressed) -> None:
        """Copy the generated schema to the definition textarea."""
        builder = self.query_one("#schema-builder", JsonSchemaBuilder)
        if builder.generated_schema:
            schema_str = json.dumps(builder.generated_schema, indent=2)
            self.query_one("#definition-textarea", TextArea).text = schema_str
            self.app.notify(
                "Generated schema copied to definition", severity="information"
            )

    @on(Button.Pressed, "#create-btn")
    def on_create_pressed(self, event: Button.Pressed) -> None:
        """Handle create 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"
            )

        definition = self.query_one("#definition-textarea", TextArea).text.strip()
        if not definition:
            raise ValueError(
                "Schema definition is required. Paste a JSON Schema or regex pattern."
            )

        # Validate JSON schema format
        schema_format = self._get_schema_format()
        if schema_format == SchemaFormat.JSON_SCHEMA:
            try:
                json.loads(definition)
            except json.JSONDecodeError as e:
                raise ValueError(f"Invalid JSON in schema definition: {e.msg}")

    def _get_schema_format(self) -> SchemaFormat:
        """Get schema format from RadioSet."""
        radios = self.query_one("#format-radios", RadioSet)
        pressed = radios.pressed_button
        if pressed is None or pressed.id == "format-json-schema":
            return SchemaFormat.JSON_SCHEMA
        return SchemaFormat.REGEX

    def _get_scope(self) -> OwnershipScope:
        """Get scope from RadioSet."""
        return get_scope_from_radioset(self.query_one("#scope-radios", RadioSet))

    def _build_request(self) -> CreateSchemaRequest:
        """Build the API request."""
        name = self.query_one("#name-input", Input).value.strip()
        definition = self.query_one("#definition-textarea", TextArea).text.strip()
        description = self.query_one("#description-input", Input).value.strip() or None

        return CreateSchemaRequest(
            name=name,
            schema_format=self._get_schema_format(),
            schema_definition=definition,
            description=description,
            scope=self._get_scope(),
        )

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

            result = SchemaCreateResult(
                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 create schema: {e}")
