"""
Variant System Types for UI Components.

This module defines types for tracking UI component variants across the
TypeScript → Pydantic → YAML SST pipeline.

Variant Categories:
    1. Style Variants - Same component, different visual styles (size, color)
    2. Implementation Variants - Different implementations of same concept (hero-01, hero-03)
    3. Composite Variants - Different arrangements of sub-components

AUTO-GENERATED - regenerate with: lw ui update
"""

from enum import Enum
from typing import Any, TypeVar

from pydantic import Field

from lightwave.schema.pydantic.core.base import JSONFieldSchema

# =============================================================================
# VARIANT CATEGORY TYPES
# =============================================================================


class VariantCategory(str, Enum):
    """
    Categories of component variants.

    STYLE: Same component with different visual treatment
           e.g., Button with size="sm" | "md" | "lg"

    IMPLEMENTATION: Different implementations of same concept
           e.g., HeroScreenMockup01, HeroScreenMockup03, HeroScreenMockup05

    COMPOSITE: Different arrangements/combinations of sub-components
           e.g., RadioGroup with IconSimple, IconCard, Avatar, etc.

    BOOLEAN: Configuration via boolean props
           e.g., Header with isFullWidth, isFloating
    """

    STYLE = "style"
    IMPLEMENTATION = "implementation"
    COMPOSITE = "composite"
    BOOLEAN = "boolean"


# =============================================================================
# STYLE VARIANT TYPES
# =============================================================================


class StyleVariantDimension(JSONFieldSchema):
    """
    A dimension of style variation (e.g., size, color, theme).

    TypeScript pattern:
        size?: keyof typeof styles.sizes  // "sm" | "md" | "lg"
    """

    name: str = Field(description="Dimension name (e.g., 'size', 'color', 'theme')")
    values: list[str] = Field(description="Valid values for this dimension")
    default: str | None = Field(default=None, description="Default value if not specified")
    description: str | None = Field(default=None, description="What this dimension controls")


class StyleVariantDefinition(JSONFieldSchema):
    """
    Definition of style-based variants for a component.

    Used for components like Button where variants are defined in a styles object
    with multiple dimensions (size, color).
    """

    component_name: str = Field(description="Component name (e.g., 'Button')")
    dimensions: list[StyleVariantDimension] = Field(description="Variant dimensions")
    styles_object_name: str = Field(default="styles", description="Name of styles object in source")
    source_file: str = Field(description="TypeScript source file path")


# =============================================================================
# IMPLEMENTATION VARIANT TYPES
# =============================================================================


class ImplementationVariant(JSONFieldSchema):
    """
    A specific implementation variant of a component concept.

    Used for components like Hero where each variant is a separate file/component:
        hero-screen-mockup-01.tsx → HeroScreenMockup01
        hero-screen-mockup-03.tsx → HeroScreenMockup03
    """

    variant_key: str = Field(description="Variant identifier (e.g., '01', '03', '05')")
    component_name: str = Field(description="Full component name (e.g., 'HeroScreenMockup01')")
    source_file: str = Field(description="TypeScript source file path")
    props_interface: str | None = Field(default=None, description="Props interface name if exported")
    description: str | None = Field(default=None, description="What makes this variant unique")


class ImplementationVariantRegistry(JSONFieldSchema):
    """
    Registry of implementation variants for a component concept.

    Example: Hero component has variants 01, 03, 05 with different layouts.
    """

    concept_name: str = Field(description="Concept name (e.g., 'Hero', 'Footer')")
    category: str = Field(description="Component category (e.g., 'marketing/header-section')")
    variants: list[ImplementationVariant] = Field(description="Available variants")
    base_props_interface: str | None = Field(default=None, description="Shared base props interface if exists")

    @property
    def variant_keys(self) -> list[str]:
        """Get list of all variant keys."""
        return [v.variant_key for v in self.variants]


# =============================================================================
# COMPOSITE VARIANT TYPES
# =============================================================================


class CompositeVariant(JSONFieldSchema):
    """
    A composite variant that combines sub-components differently.

    Used for components like RadioGroup where each variant uses different
    sub-component arrangements: IconSimple, IconCard, Avatar, PaymentIcon, etc.
    """

    variant_key: str = Field(description="Variant identifier (e.g., 'IconSimple', 'IconCard')")
    export_name: str = Field(description="Exported name (e.g., 'IconSimple' from 'RadioGroupIconSimple')")
    component_name: str = Field(description="Full component name")
    source_file: str = Field(description="TypeScript source file path")
    item_type: str | None = Field(default=None, description="Item type for list-based variants")
    props_interface: str | None = Field(default=None, description="Props interface name")


class CompositeVariantRegistry(JSONFieldSchema):
    """
    Registry of composite variants for a component family.

    Example: RadioGroup has variants IconSimple, IconCard, Avatar, etc.
    """

    family_name: str = Field(description="Family name (e.g., 'RadioGroup')")
    category: str = Field(description="Component category (e.g., 'base/radio-groups')")
    barrel_export_file: str | None = Field(default=None, description="File that re-exports all variants")
    variants: list[CompositeVariant] = Field(description="Available variants")

    @property
    def variant_keys(self) -> list[str]:
        """Get list of all variant keys."""
        return [v.variant_key for v in self.variants]


# =============================================================================
# BOOLEAN VARIANT TYPES
# =============================================================================


class BooleanVariantProp(JSONFieldSchema):
    """
    A boolean prop that enables a variant behavior.

    TypeScript pattern:
        isFloating?: boolean;
        isFullWidth?: boolean;
    """

    name: str = Field(description="Prop name (e.g., 'isFloating', 'isFullWidth')")
    description: str | None = Field(default=None, description="What this prop enables")
    default: bool = Field(default=False, description="Default value")
    affects: list[str] | None = Field(default=None, description="What CSS/behavior this affects")


class BooleanVariantDefinition(JSONFieldSchema):
    """
    Definition of boolean-prop-based variants for a component.

    Used for components like Header where variants are controlled by
    boolean props: isFloating, isFullWidth.
    """

    component_name: str = Field(description="Component name (e.g., 'Header')")
    props: list[BooleanVariantProp] = Field(description="Boolean variant props")
    source_file: str = Field(description="TypeScript source file path")

    @property
    def variant_combinations(self) -> int:
        """Number of possible variant combinations (2^n)."""
        return 2 ** len(self.props)


# =============================================================================
# UNIFIED VARIANT METADATA
# =============================================================================


class ComponentVariantMetadata(JSONFieldSchema):
    """
    Complete variant metadata for a component.

    Captures all variant patterns a component might use.
    A component can use multiple patterns simultaneously.
    """

    component_name: str = Field(description="Primary component name")
    category: str = Field(description="Component category path")
    source_files: list[str] = Field(description="All related source files")

    # Variant patterns (a component may use multiple)
    style_variants: StyleVariantDefinition | None = Field(
        default=None, description="Style-based variants (size, color)"
    )
    implementation_variants: ImplementationVariantRegistry | None = Field(
        default=None, description="Separate implementation variants"
    )
    composite_variants: CompositeVariantRegistry | None = Field(
        default=None, description="Composite arrangement variants"
    )
    boolean_variants: BooleanVariantDefinition | None = Field(default=None, description="Boolean prop variants")

    @property
    def variant_categories(self) -> list[VariantCategory]:
        """Get list of variant categories this component uses."""
        categories = []
        if self.style_variants:
            categories.append(VariantCategory.STYLE)
        if self.implementation_variants:
            categories.append(VariantCategory.IMPLEMENTATION)
        if self.composite_variants:
            categories.append(VariantCategory.COMPOSITE)
        if self.boolean_variants:
            categories.append(VariantCategory.BOOLEAN)
        return categories


# =============================================================================
# ITEM TYPES FOR LIST-BASED VARIANTS
# =============================================================================


class RadioGroupItemType(JSONFieldSchema):
    """
    Item type for RadioGroup variants.

    TypeScript source: base/radio-groups/radio-group-icon-simple.tsx
    """

    value: str = Field(description="Value when selected")
    title: str = Field(description="Display title")
    description: str = Field(description="Description text")
    secondary_title: str = Field(
        alias="secondaryTitle",
        serialization_alias="secondaryTitle",
        description="Secondary title",
    )
    disabled: bool | None = Field(default=None, description="Whether item is disabled")
    icon: str = Field(description="Icon component name")


class IconCardItemType(JSONFieldSchema):
    """Item type for IconCard RadioGroup variant."""

    value: str = Field(description="Value when selected")
    title: str = Field(description="Display title")
    icon: str = Field(description="Icon component name")
    disabled: bool | None = Field(default=None, description="Whether item is disabled")


class PaymentCardItemType(JSONFieldSchema):
    """Item type for PaymentIcon RadioGroup variant."""

    value: str = Field(description="Value when selected")
    label: str = Field(description="Display label")
    icon: str = Field(description="Payment icon component name")
    disabled: bool | None = Field(default=None, description="Whether item is disabled")


class AvatarItemType(JSONFieldSchema):
    """Item type for Avatar RadioGroup variant."""

    value: str = Field(description="Value when selected")
    name: str = Field(description="Display name")
    avatar_url: str = Field(
        alias="avatarUrl",
        serialization_alias="avatarUrl",
        description="Avatar image URL",
    )
    disabled: bool | None = Field(default=None, description="Whether item is disabled")


# =============================================================================
# GENERIC VARIANT REGISTRY TYPE
# =============================================================================

T = TypeVar("T")


class VariantRegistry(JSONFieldSchema):
    """
    Generic registry for any variant type.

    Used for dynamically tracking variants discovered during extraction.
    """

    registry_name: str = Field(description="Name of this registry")
    variant_type: VariantCategory = Field(description="Type of variants in this registry")
    variants: dict[str, Any] = Field(default_factory=dict, description="Variant key → metadata")


# =============================================================================
# EXPORTS
# =============================================================================

__all__ = [
    # Categories
    "VariantCategory",
    # Style variants
    "StyleVariantDimension",
    "StyleVariantDefinition",
    # Implementation variants
    "ImplementationVariant",
    "ImplementationVariantRegistry",
    # Composite variants
    "CompositeVariant",
    "CompositeVariantRegistry",
    # Boolean variants
    "BooleanVariantProp",
    "BooleanVariantDefinition",
    # Unified metadata
    "ComponentVariantMetadata",
    # Item types
    "RadioGroupItemType",
    "IconCardItemType",
    "PaymentCardItemType",
    "AvatarItemType",
    # Generic
    "VariantRegistry",
]
