from typing import Any, Optional

from ninja import Schema


# Form metadata schema
class FormMeta(Schema):
    """
    Metadata controlling frontend form behavior.

    Attributes:
        refetch_schema_on_validate: If True, frontend should refetch schema on each
            validation (useful for dynamic choice fields). Default False.
        live_validation: If False, frontend should disable live validation entirely.
            Useful for sensitive forms like login. Default True.
        live_form_errors: If True, show form-level errors during live validation.
            Form errors are things like "Invalid credentials" vs field errors like
            "This field is required". Default False for security.
    """
    refetch_schema_on_validate: bool = False
    live_validation: bool = True
    live_form_errors: bool = False


# Field-level schemas
class FieldChoice(Schema):
    value: str
    label: str


class FieldError(Schema):
    message: str
    code: Optional[str]


class FieldErrorList(Schema):
    field: str
    errors: list[FieldError]


class FieldSchema(Schema):
    name: str
    label: str
    type: str
    widget: str
    required: bool
    disabled: bool
    help_text: str
    initial: Any
    max_length: Optional[int]
    min_length: Optional[int]
    choices: Optional[list[FieldChoice]]


# Form-level schemas
class FormSchema(Schema):
    """Schema returned by /schema endpoint with form metadata and fields."""
    # Form metadata
    name: str
    title: str
    subtitle: Optional[str]
    submit_label: str
    # Fields
    fields: list[FieldSchema]
    # Frontend behavior metadata
    meta: FormMeta = FormMeta()


class FormValidation(Schema):
    errors: list[FieldErrorList]


class FormSubmitPass(Schema):
    success: bool
    data: Optional[dict] = None


class FormSubmitFail(Schema):
    success: bool
    errors: FormValidation


# Formset-level schemas
class FormsetSchema(Schema):
    forms: list[FormSchema]
    min_num: int
    max_num: int
    can_delete: bool
    can_order: bool


class FormsetValidation(Schema):
    general: list[str]
    per_form: list[FormValidation]


class FormsetSubmitPass(Schema):
    success: bool


class FormsetSubmitFail(Schema):
    success: bool
    errors: FormsetValidation
