"""
System Configuration Model
Application settings and map provider configuration
"""
import enum
from datetime import datetime
from typing import Optional
from sqlalchemy import String, Boolean, Enum, Text, DateTime, Index, JSON
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import BaseModel


class MapProviderType(str, enum.Enum):
    """Supported map providers"""
    MAPBOX = "mapbox"
    GOOGLE_MAPS = "google_maps"
    OPENSTREETMAP = "openstreetmap"


class ConfigCategory(str, enum.Enum):
    """Configuration category"""
    GENERAL = "general"
    MAP_PROVIDER = "map_provider"
    PAYMENT = "payment"
    NOTIFICATION = "notification"
    RIDE = "ride"
    FARE = "fare"
    COMMISSION = "commission"
    SMS = "sms"
    EMAIL = "email"
    SECURITY = "security"


class SystemConfig(BaseModel):
    """
    Key-value system configuration storage.
    Allows dynamic configuration without code changes.
    """
    __tablename__ = "system_configs"
    
    # Configuration key (unique identifier)
    key: Mapped[str] = mapped_column(
        String(100),
        unique=True,
        nullable=False,
        index=True
    )
    
    # Value (stored as text, parsed based on value_type)
    value: Mapped[str] = mapped_column(Text, nullable=False)
    value_type: Mapped[str] = mapped_column(
        String(20),
        default="string",
        nullable=False
    )  # string, int, float, bool, json
    
    # Category for grouping
    category: Mapped[ConfigCategory] = mapped_column(
        Enum(ConfigCategory),
        default=ConfigCategory.GENERAL,
        nullable=False,
        index=True
    )
    
    # Description for admin panel
    label: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    
    # Validation
    is_required: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_encrypted: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    
    # Editability
    is_editable: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    is_visible: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    
    # Indexes
    __table_args__ = (
        Index('idx_config_category', 'category'),
    )
    
    def get_typed_value(self):
        """Get value with proper type casting"""
        if self.value_type == "int":
            return int(self.value)
        elif self.value_type == "float":
            return float(self.value)
        elif self.value_type == "bool":
            return self.value.lower() in ("true", "1", "yes")
        elif self.value_type == "json":
            import json
            return json.loads(self.value)
        return self.value


class MapProviderConfig(BaseModel):
    """
    Map provider configuration.
    Allows switching between different map providers via admin panel.
    """
    __tablename__ = "map_provider_configs"
    
    # Provider identification
    provider_name: Mapped[MapProviderType] = mapped_column(
        Enum(MapProviderType),
        unique=True,
        nullable=False,
        index=True
    )
    
    display_name: Mapped[str] = mapped_column(String(100), nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    
    # API Configuration (encrypted in production)
    api_key: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    api_secret: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    api_url: Mapped[Optional[str]] = mapped_column(String(500), nullable=True)
    
    # Provider-specific settings (JSON for flexibility)
    settings: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
    
    # Status
    is_active: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        nullable=False,
        index=True
    )
    is_configured: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    
    # Priority (for fallback ordering)
    priority: Mapped[int] = mapped_column(default=0, nullable=False)
    
    # Last tested
    last_tested_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    last_test_status: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    
    # Indexes
    __table_args__ = (
        Index('idx_map_provider_active', 'is_active'),
    )


# Default configuration values
DEFAULT_CONFIGS = [
    # General
    {"key": "app_name", "value": "Transporter", "category": "general", "label": "Application Name"},
    {"key": "support_email", "value": "support@example.com", "category": "general", "label": "Support Email"},
    {"key": "support_phone", "value": "+1234567890", "category": "general", "label": "Support Phone"},
    
    # Ride
    {"key": "max_booking_distance_km", "value": "100", "value_type": "int", "category": "ride", "label": "Max Booking Distance (km)"},
    {"key": "driver_search_radius_km", "value": "10", "value_type": "float", "category": "ride", "label": "Driver Search Radius (km)"},
    {"key": "bid_expiry_seconds", "value": "60", "value_type": "int", "category": "ride", "label": "Bid Expiry Time (seconds)"},
    {"key": "max_active_rides_per_driver", "value": "1", "value_type": "int", "category": "ride", "label": "Max Active Rides Per Driver"},
    
    # Fare
    {"key": "default_base_fare", "value": "5000", "value_type": "int", "category": "fare", "label": "Default Base Fare (cents)"},
    {"key": "default_per_km_rate", "value": "1500", "value_type": "int", "category": "fare", "label": "Default Per KM Rate (cents)"},
    {"key": "default_per_minute_rate", "value": "200", "value_type": "int", "category": "fare", "label": "Default Per Minute Rate (cents)"},
    
    # Commission
    {"key": "default_commission_percentage", "value": "15", "value_type": "float", "category": "commission", "label": "Default Commission (%)"},
    {"key": "min_withdrawal_amount", "value": "1000", "value_type": "int", "category": "commission", "label": "Min Withdrawal Amount (cents)"},
    
    # Security
    {"key": "max_otp_attempts", "value": "5", "value_type": "int", "category": "security", "label": "Max OTP Attempts"},
    {"key": "otp_expiry_minutes", "value": "5", "value_type": "int", "category": "security", "label": "OTP Expiry (minutes)"},
]
