"""
GigLez Environment Configuration

Handles environment-based settings for development and production modes
"""

import os
from enum import Enum
from typing import Optional, List
from pathlib import Path
from loguru import logger
from dotenv import load_dotenv


# =============================================================================
# LOAD ENVIRONMENT
# =============================================================================

# Determine which .env file to load
MODE = os.getenv("GIGLEZ_MODE", "development")

if MODE == "production":
    env_file = ".env.production"
elif MODE == "development":
    env_file = ".env.development"
else:
    env_file = ".env"

# Load environment variables
env_path = Path(__file__).parent.parent / env_file
if env_path.exists():
    load_dotenv(env_path)
    logger.info(f"Loaded environment from: {env_file}")
else:
    logger.warning(f"Environment file not found: {env_file}, using defaults")


# =============================================================================
# ENUMS
# =============================================================================

class DeploymentMode(str, Enum):
    """Deployment mode enumeration"""
    DEVELOPMENT = "development"
    PRODUCTION = "production"


class StorageType(str, Enum):
    """Storage backend types"""
    FILESYSTEM = "filesystem"
    S3 = "s3"


class BackgroundMode(str, Enum):
    """Background task processing mode"""
    SYNC = "sync"  # Synchronous (development)
    CELERY = "celery"  # Celery async (production)


class LogFormat(str, Enum):
    """Log output format"""
    TEXT = "text"
    JSON = "json"


# =============================================================================
# SETTINGS CLASS
# =============================================================================

class Settings:
    """
    Application settings with environment-based configuration

    Supports both development (Termux) and production (Server) modes
    """

    def __init__(self):
        """Initialize settings from environment variables"""

        # =================================================================
        # DEPLOYMENT MODE
        # =================================================================
        self.mode = DeploymentMode(os.getenv("GIGLEZ_MODE", "development"))

        # =================================================================
        # DATABASE
        # =================================================================
        self.db_host = os.getenv("GIGLEZ_DB_HOST", "localhost")
        self.db_port = int(os.getenv("GIGLEZ_DB_PORT", "5432"))
        self.db_name = os.getenv("GIGLEZ_DB_NAME", "giglez")
        self.db_user = os.getenv("GIGLEZ_DB_USER", "giglez_user")
        self.db_password = os.getenv("GIGLEZ_DB_PASSWORD", "giglez_secure_password_2026")
        self.db_pool_size = int(os.getenv("GIGLEZ_DB_POOL_SIZE", "10"))
        self.db_max_overflow = int(os.getenv("GIGLEZ_DB_MAX_OVERFLOW", "20"))
        self.db_echo = os.getenv("GIGLEZ_DB_ECHO", "false").lower() == "true"

        # =================================================================
        # API
        # =================================================================
        self.api_host = os.getenv("GIGLEZ_API_HOST", "0.0.0.0")
        self.api_port = int(os.getenv("GIGLEZ_API_PORT", "8000"))
        self.api_workers = int(os.getenv("GIGLEZ_API_WORKERS", "4"))

        # CORS
        cors_origins = os.getenv("GIGLEZ_API_CORS_ORIGINS", "*")
        self.cors_origins = [o.strip() for o in cors_origins.split(",")] if cors_origins != "*" else ["*"]

        # Authentication
        self.require_auth = os.getenv("GIGLEZ_REQUIRE_AUTH", "true").lower() == "true"
        self.jwt_secret_key = os.getenv("GIGLEZ_JWT_SECRET_KEY", "dev-secret-key")
        self.jwt_algorithm = os.getenv("GIGLEZ_JWT_ALGORITHM", "HS256")
        self.jwt_expire_minutes = int(os.getenv("GIGLEZ_JWT_EXPIRE_MINUTES", "1440"))

        # =================================================================
        # FILE STORAGE
        # =================================================================
        self.storage_type = StorageType(os.getenv("GIGLEZ_STORAGE_TYPE", "filesystem"))
        self.storage_path = os.getenv("GIGLEZ_STORAGE_PATH", "./storage")
        self.storage_bucket = os.getenv("GIGLEZ_STORAGE_BUCKET", "giglez-captures")
        self.s3_endpoint = os.getenv("GIGLEZ_S3_ENDPOINT", "https://s3.amazonaws.com")

        # AWS credentials (for S3)
        self.aws_access_key_id = os.getenv("AWS_ACCESS_KEY_ID")
        self.aws_secret_access_key = os.getenv("AWS_SECRET_ACCESS_KEY")
        self.aws_region = os.getenv("AWS_REGION", "us-east-1")

        # Upload limits
        self.max_upload_size = int(os.getenv("GIGLEZ_MAX_UPLOAD_SIZE", "10485760"))  # 10MB
        self.max_batch_files = int(os.getenv("GIGLEZ_MAX_BATCH_FILES", "100"))

        # =================================================================
        # HARDWARE (Termux specific)
        # =================================================================
        self.enable_hardware = os.getenv("GIGLEZ_ENABLE_HARDWARE", "false").lower() == "true"
        self.tembed_port = os.getenv("GIGLEZ_TEMBED_PORT", "/dev/ttyUSB0")
        self.tembed_baud = int(os.getenv("GIGLEZ_TEMBED_BAUD", "115200"))
        self.gps_provider = os.getenv("GIGLEZ_GPS_PROVIDER", "termux-api")

        # =================================================================
        # PERFORMANCE
        # =================================================================
        self.batch_size = int(os.getenv("GIGLEZ_BATCH_SIZE", "512"))
        self.cache_size = int(os.getenv("GIGLEZ_CACHE_SIZE", "256"))
        self.redis_url = os.getenv("GIGLEZ_REDIS_URL", "")
        self.background_mode = BackgroundMode(os.getenv("GIGLEZ_BACKGROUND_MODE", "sync"))

        # Celery (if background_mode == celery)
        self.celery_broker = os.getenv("GIGLEZ_CELERY_BROKER", "redis://localhost:6379/1")
        self.celery_result_backend = os.getenv("GIGLEZ_CELERY_RESULT_BACKEND", "redis://localhost:6379/2")

        # =================================================================
        # LOGGING
        # =================================================================
        self.log_level = os.getenv("GIGLEZ_LOG_LEVEL", "INFO")
        self.log_file = os.getenv("GIGLEZ_LOG_FILE", "")
        self.log_colorize = os.getenv("GIGLEZ_LOG_COLORIZE", "true").lower() == "true"
        self.log_format = LogFormat(os.getenv("GIGLEZ_LOG_FORMAT", "text"))

        # =================================================================
        # GPS VALIDATION
        # =================================================================
        self.gps_max_accuracy = float(os.getenv("GIGLEZ_GPS_MAX_ACCURACY", "50.0"))
        self.gps_min_accuracy = float(os.getenv("GIGLEZ_GPS_MIN_ACCURACY", "10.0"))

        # =================================================================
        # OFFLINE SUPPORT (Development)
        # =================================================================
        self.enable_offline_queue = os.getenv("GIGLEZ_ENABLE_OFFLINE_QUEUE", "false").lower() == "true"
        self.queue_path = os.getenv("GIGLEZ_QUEUE_PATH", "./queue")
        self.auto_upload = os.getenv("GIGLEZ_AUTO_UPLOAD", "true").lower() == "true"

        # =================================================================
        # SECURITY (Production)
        # =================================================================
        self.rate_limit_enabled = os.getenv("GIGLEZ_RATE_LIMIT_ENABLED", "false").lower() == "true"
        self.rate_limit_per_minute = int(os.getenv("GIGLEZ_RATE_LIMIT_PER_MINUTE", "60"))
        self.rate_limit_per_hour = int(os.getenv("GIGLEZ_RATE_LIMIT_PER_HOUR", "1000"))
        self.force_https = os.getenv("GIGLEZ_FORCE_HTTPS", "false").lower() == "true"

        # =================================================================
        # FEATURES
        # =================================================================
        self.debug_endpoints = os.getenv("GIGLEZ_DEBUG_ENDPOINTS", "false").lower() == "true"
        self.auto_reload = os.getenv("GIGLEZ_AUTO_RELOAD", "false").lower() == "true"
        self.debug_errors = os.getenv("GIGLEZ_DEBUG_ERRORS", "false").lower() == "true"
        self.enable_metrics = os.getenv("GIGLEZ_ENABLE_METRICS", "false").lower() == "true"

        # =================================================================
        # SIGNATURE DATABASES
        # =================================================================
        self.signature_auto_update = os.getenv("GIGLEZ_SIGNATURE_AUTO_UPDATE", "false").lower() == "true"
        self.signature_update_cron = os.getenv("GIGLEZ_SIGNATURE_UPDATE_CRON", "0 2 * * *")

    # =====================================================================
    # COMPUTED PROPERTIES
    # =====================================================================

    @property
    def is_production(self) -> bool:
        """Check if running in production mode"""
        return self.mode == DeploymentMode.PRODUCTION

    @property
    def is_development(self) -> bool:
        """Check if running in development mode"""
        return self.mode == DeploymentMode.DEVELOPMENT

    @property
    def database_url(self) -> str:
        """Get database connection URL"""
        return f"postgresql://{self.db_user}:{self.db_password}@{self.db_host}:{self.db_port}/{self.db_name}"

    @property
    def database_url_safe(self) -> str:
        """Get database URL without password (for logging)"""
        return f"postgresql://{self.db_user}:****@{self.db_host}:{self.db_port}/{self.db_name}"

    @property
    def use_redis(self) -> bool:
        """Check if Redis is configured"""
        return bool(self.redis_url)

    @property
    def use_celery(self) -> bool:
        """Check if Celery background tasks are enabled"""
        return self.background_mode == BackgroundMode.CELERY

    @property
    def use_s3_storage(self) -> bool:
        """Check if S3 storage is configured"""
        return self.storage_type == StorageType.S3

    @property
    def use_local_storage(self) -> bool:
        """Check if local filesystem storage is configured"""
        return self.storage_type == StorageType.FILESYSTEM

    # =====================================================================
    # VALIDATION
    # =====================================================================

    def validate(self) -> List[str]:
        """
        Validate configuration

        Returns:
            List of validation errors (empty if valid)
        """
        errors = []

        # Production checks
        if self.is_production:
            if self.jwt_secret_key == "dev-secret-key":
                errors.append("JWT secret key must be changed in production")

            if not self.require_auth:
                errors.append("Authentication must be enabled in production")

            if self.debug_endpoints:
                errors.append("Debug endpoints should be disabled in production")

            if self.use_s3_storage and not (self.aws_access_key_id and self.aws_secret_access_key):
                errors.append("AWS credentials required for S3 storage")

        # Development checks
        if self.is_development:
            if self.enable_hardware and not os.path.exists(self.tembed_port):
                logger.warning(f"T-Embed port not found: {self.tembed_port}")

        # Storage checks
        if self.use_local_storage:
            storage_path = Path(self.storage_path)
            if not storage_path.exists():
                try:
                    storage_path.mkdir(parents=True, exist_ok=True)
                    logger.info(f"Created storage directory: {storage_path}")
                except Exception as e:
                    errors.append(f"Cannot create storage directory: {e}")

        # Queue checks
        if self.enable_offline_queue:
            queue_path = Path(self.queue_path)
            if not queue_path.exists():
                try:
                    queue_path.mkdir(parents=True, exist_ok=True)
                    logger.info(f"Created queue directory: {queue_path}")
                except Exception as e:
                    errors.append(f"Cannot create queue directory: {e}")

        return errors

    # =====================================================================
    # DISPLAY
    # =====================================================================

    def display(self):
        """Display current configuration"""
        logger.info("=" * 60)
        logger.info("GigLez Configuration")
        logger.info("=" * 60)
        logger.info(f"Mode: {self.mode.value}")
        logger.info(f"Database: {self.database_url_safe}")
        logger.info(f"API: {self.api_host}:{self.api_port}")
        logger.info(f"Storage: {self.storage_type.value}")
        logger.info(f"Hardware: {'Enabled' if self.enable_hardware else 'Disabled'}")
        logger.info(f"Authentication: {'Required' if self.require_auth else 'Optional'}")
        logger.info(f"Background Tasks: {self.background_mode.value}")
        logger.info(f"Redis: {'Enabled' if self.use_redis else 'Disabled'}")
        logger.info(f"Log Level: {self.log_level}")
        logger.info("=" * 60)

        # Validation
        errors = self.validate()
        if errors:
            logger.error("Configuration errors:")
            for error in errors:
                logger.error(f"  - {error}")
        else:
            logger.success("Configuration validated successfully")


# =============================================================================
# GLOBAL SETTINGS INSTANCE
# =============================================================================

settings = Settings()


# =============================================================================
# HELPER FUNCTIONS
# =============================================================================

def get_settings() -> Settings:
    """Get global settings instance"""
    return settings


def reload_settings():
    """Reload settings from environment"""
    global settings
    settings = Settings()
    return settings


# =============================================================================
# TESTING
# =============================================================================

if __name__ == "__main__":
    # Display configuration
    settings.display()

    # Test validation
    print("\nValidation Results:")
    errors = settings.validate()
    if errors:
        print("Errors found:")
        for error in errors:
            print(f"  ❌ {error}")
    else:
        print("  ✅ Configuration is valid")

    # Test properties
    print("\nComputed Properties:")
    print(f"  is_production: {settings.is_production}")
    print(f"  is_development: {settings.is_development}")
    print(f"  use_redis: {settings.use_redis}")
    print(f"  use_celery: {settings.use_celery}")
    print(f"  use_s3_storage: {settings.use_s3_storage}")
    print(f"  use_local_storage: {settings.use_local_storage}")
