"""
Sandai Operator SDK - Environment Configuration

统一管理环境变量配置，包括运行环境、OSS 配置、Celery 配置等。
算子层代码不应直接配置这些基础设施信息，而应通过此模块获取。
"""

import os
from typing import Optional, Dict, Any
from dataclasses import dataclass
from dotenv import load_dotenv, find_dotenv
import logging

logger = logging.getLogger(__name__)
_DEFAULT_CELERY_ACCEPT_CONTENT = ["json", "msgpack"]

dotenv_path = find_dotenv(usecwd=True) or find_dotenv()
load_dotenv(dotenv_path)
cliam_env = os.getenv("SANDAI_OPERATOR_ENV", "dev")
dotenv_path = find_dotenv(f".env.{cliam_env}", usecwd=True) or find_dotenv()
load_dotenv(dotenv_path)

@dataclass
class OSSConfig:
    """OSS 配置"""

    endpoint: str
    vpc_endpoint: str
    access_key_id: str
    access_key_secret: str
    bucket_name: str
    region: str
    prefix: str = "processed"
    io_via: str = "external"

    @property
    def is_configured(self) -> bool:
        """检查 OSS 是否已配置"""
        return all(
            [
                self.endpoint,
                self.vpc_endpoint,
                self.access_key_id,
                self.access_key_secret,
                self.bucket_name,
                self.region,
                self.io_via,
            ]
        )

    @property
    def has_vpc_endpoint(self) -> bool:
        """检查是否配置了 VPC 端点"""
        return bool(self.vpc_endpoint)


@dataclass
class MinIOConfig:
    """MinIO (S3 兼容) 配置"""

    endpoint: str
    access_key: str
    secret_key: str
    bucket_name: str
    region: str = "us-east-1"
    secure: bool = False  # 是否使用 HTTPS
    prefix: str = "processed"

    @property
    def is_configured(self) -> bool:
        """检查 MinIO 是否已配置"""
        return all([self.endpoint, self.access_key, self.secret_key, self.bucket_name])


@dataclass
class CeleryConfig:
    """Celery 配置"""

    broker_url: str
    result_backend: str
    task_serializer: str = "json"
    result_serializer: str = "json"
    accept_content: list = None

    def __post_init__(self):
        if self.accept_content is None:
            self.accept_content = list(_DEFAULT_CELERY_ACCEPT_CONTENT)

    @property
    def is_configured(self) -> bool:
        """检查 Celery 是否已配置"""
        return bool(self.broker_url and self.result_backend)


def get_environment() -> str:
    """
    获取运行环境

    Returns:
        str: 运行环境 ('dev', 'test', 'prod')
    """
    return os.getenv("SANDAI_OPERATOR_ENV", "dev").lower()


def is_development() -> bool:
    """
    检查是否为开发环境

    Returns:
        bool: True if development environment
    """
    return get_environment() == "dev"


def is_production() -> bool:
    """
    检查是否为生产环境

    Returns:
        bool: True if production environment
    """
    return get_environment() == "prod"


def get_sentry_dsn() -> Optional[str]:
    """
    获取 Sentry DSN

    Returns:
        Optional[str]: Sentry DSN
    """
    return os.getenv("SANDAI_OPERATOR_SENTRY_DSN", None)


def get_minio_config() -> Optional[MinIOConfig]:
    """
    获取 MinIO 配置

    环境变量:
        SANDAI_OPERATOR_MINIO_ENDPOINT: MinIO 端点 (默认: localhost:9000)
        SANDAI_OPERATOR_MINIO_ACCESS_KEY: Access Key (默认: minioadmin)
        SANDAI_OPERATOR_MINIO_SECRET_KEY: Secret Key (默认: minioadmin)
        SANDAI_OPERATOR_MINIO_BUCKET: Bucket 名称 (默认: sandai-artifacts)
        SANDAI_OPERATOR_MINIO_REGION: 区域 (默认: us-east-1)
        SANDAI_OPERATOR_MINIO_SECURE: 是否使用 HTTPS (默认: false)
        SANDAI_OPERATOR_MINIO_PREFIX: 对象前缀 (默认: processed)

    Returns:
        MinIOConfig: MinIO 配置，使用默认值如果未配置
    """
    endpoint = os.getenv("SANDAI_OPERATOR_MINIO_ENDPOINT", "localhost:9000")
    access_key = os.getenv("SANDAI_OPERATOR_MINIO_ACCESS_KEY", "minioadmin")
    secret_key = os.getenv("SANDAI_OPERATOR_MINIO_SECRET_KEY", "minioadmin")
    bucket_name = os.getenv("SANDAI_OPERATOR_MINIO_BUCKET", "operators-data-exchange")
    region = os.getenv("SANDAI_OPERATOR_MINIO_REGION", "us-east-1")
    secure = os.getenv("SANDAI_OPERATOR_MINIO_SECURE", "false").lower() == "true"
    prefix = os.getenv("SANDAI_OPERATOR_MINIO_PREFIX", "processed")

    return MinIOConfig(
        endpoint=endpoint,
        access_key=access_key,
        secret_key=secret_key,
        bucket_name=bucket_name,
        region=region,
        secure=secure,
        prefix=prefix,
    )


def get_oss_config() -> Optional[OSSConfig]:
    """
    获取 OSS 配置

    环境变量:
        SANDAI_OPERATOR_OSS_ENDPOINT: OSS 端点
        SANDAI_OPERATOR_OSS_VPC_ENDPOINT: OSS VPC 内网端点
        SANDAI_OPERATOR_OSS_IO_VIA: 通过什么网络做 IO (默认: external)
        SANDAI_OPERATOR_OSS_ACCESS_KEY_ID: Access Key ID
        SANDAI_OPERATOR_OSS_ACCESS_KEY_SECRET: Access Key Secret
        SANDAI_OPERATOR_OSS_BUCKET: Bucket 名称
        SANDAI_OPERATOR_OSS_REGION: 区域
        SANDAI_OPERATOR_OSS_PREFIX: 对象前缀 (可选，默认: processed)

    Returns:
        Optional[OSSConfig]: OSS 配置，如果未配置则返回 None
    """
    endpoint = os.getenv("SANDAI_OPERATOR_OSS_ENDPOINT", "oss-cn-shanghai.aliyuncs.com")
    vpc_endpoint = os.getenv(
        "SANDAI_OPERATOR_OSS_VPC_ENDPOINT", "oss-cn-shanghai-internal.aliyuncs.com"
    )
    io_via = os.getenv("SANDAI_OPERATOR_OSS_IO_VIA", "external").lower()
    access_key_id = os.getenv("SANDAI_OPERATOR_OSS_ACCESS_KEY_ID")
    access_key_secret = os.getenv("SANDAI_OPERATOR_OSS_ACCESS_KEY_SECRET")
    bucket_name = os.getenv("SANDAI_OPERATOR_OSS_BUCKET", "sandwave-yt")
    region = os.getenv("SANDAI_OPERATOR_OSS_REGION", "oss-cn-shanghai")
    prefix = os.getenv("SANDAI_OPERATOR_OSS_PREFIX", "operators-data-exchange")

    if not all(
        [
            endpoint,
            vpc_endpoint,
            access_key_id,
            access_key_secret,
            bucket_name,
            region,
            prefix,
            io_via,
        ]
    ):
        return None

    return OSSConfig(
        endpoint=endpoint,
        vpc_endpoint=vpc_endpoint,
        access_key_id=access_key_id,
        access_key_secret=access_key_secret,
        bucket_name=bucket_name,
        region=region,
        prefix=prefix,
        io_via=io_via,
    )


def get_celery_config() -> Optional[CeleryConfig]:
    """
    获取 Celery 配置

    环境变量:
        SANDAI_OPERATOR_CELERY_BROKER_URL: Celery Broker URL
        SANDAI_OPERATOR_CELERY_RESULT_BACKEND: Celery Result Backend URL
        SANDAI_OPERATOR_CELERY_TASK_SERIALIZER: 任务序列化器 (可选，默认: json)
        SANDAI_OPERATOR_CELERY_RESULT_SERIALIZER: 结果序列化器 (可选，默认: json)

    Returns:
        Optional[CeleryConfig]: Celery 配置，如果未配置则返回 None
    """
    broker_url = os.getenv("SANDAI_OPERATOR_CELERY_BROKER_URL")
    result_backend = os.getenv("SANDAI_OPERATOR_CELERY_RESULT_BACKEND", broker_url)
    task_serializer = os.getenv("SANDAI_OPERATOR_CELERY_TASK_SERIALIZER", "json")
    result_serializer = os.getenv("SANDAI_OPERATOR_CELERY_RESULT_SERIALIZER", "json")

    if not (broker_url and result_backend):
        return None

    return CeleryConfig(
        broker_url=broker_url,
        result_backend=result_backend,
        task_serializer=task_serializer,
        result_serializer=result_serializer,
    )


def get_default_celery_config() -> CeleryConfig:
    """
    获取默认 Celery 配置（用于开发环境）

    Returns:
        CeleryConfig: 默认 Celery 配置
    """
    return CeleryConfig(
        broker_url="redis://localhost:6379/0", result_backend="redis://localhost:6379/0"
    )


def get_temp_dir() -> str:
    """
    获取临时文件目录

    环境变量:
        SANDAI_OPERATOR_TEMP_DIR: 临时文件目录路径

    Returns:
        str: 临时文件目录路径，默认为 ./var/artifacts
    """
    return os.getenv("SANDAI_OPERATOR_TEMP_DIR", "./var/artifacts")


def get_log_level() -> str:
    """
    获取日志级别

    环境变量:
        SANDAI_OPERATOR_LOG_LEVEL: 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)

    Returns:
        str: 日志级别，默认为 INFO
    """
    return os.getenv("SANDAI_OPERATOR_LOG_LEVEL", "INFO").upper()


def get_max_workers() -> int:
    """
    获取最大工作线程数

    环境变量:
        SANDAI_OPERATOR_MAX_WORKERS: 最大工作线程数

    Returns:
        int: 最大工作线程数，默认为 CPU 核心数
    """
    import multiprocessing

    default_workers = multiprocessing.cpu_count()
    return int(os.getenv("SANDAI_OPERATOR_MAX_WORKERS", str(default_workers)))


def get_visibility_timeout() -> int:
    """
    获取默认的消息可见性超时时间

    环境变量:
        SANDAI_OPERATOR_VISIBILITY_TIMEOUT: 消息可见性超时时间（秒）

    Returns:
        int: 可见性超时时间，默认为 300 秒（5分钟）
    """
    return int(os.getenv("SANDAI_OPERATOR_VISIBILITY_TIMEOUT", "300"))


def get_job_mode_timeout() -> int:
    """
    获取 Job Mode 超时时间

    环境变量:
        SANDAI_OPERATOR_JOB_MODE_TIMEOUT: Job Mode 超时时间（秒）

    Returns:
        int: Job Mode 超时时间，默认为 30 秒
    """
    return int(os.getenv("SANDAI_OPERATOR_JOB_MODE_TIMEOUT", "30"))


def get_celery_result_expires() -> int:
    """
    获取 Celery 结果过期时间

    环境变量:
        SANDAI_OPERATOR_CELERY_RESULT_EXPIRES: Celery 结果过期时间（秒）

    Returns:
        int: 结果过期时间，默认为 7200 秒（2小时）
    """
    return int(os.getenv("SANDAI_OPERATOR_CELERY_RESULT_EXPIRES", "7200"))


def get_celery_max_delivery_attempts() -> int:
    """
    获取 Celery 任务的最大投递次数

    环境变量:
        SANDAI_OPERATOR_CELERY_MAX_DELIVERY_ATTEMPTS: Celery 任务最大投递次数

    Returns:
        int: 最大投递次数，默认为 0（禁用上限控制）
    """
    return int(os.getenv("SANDAI_OPERATOR_CELERY_MAX_DELIVERY_ATTEMPTS", "0"))


def get_oss_signed_url_expires() -> int:
    """
    获取 OSS 签名 URL 过期时间

    环境变量:
        SANDAI_OPERATOR_OSS_SIGNED_URL_EXPIRES: OSS 签名 URL 过期时间（秒）

    Returns:
        int: 签名 URL 过期时间，默认为 3600 秒（1小时）
    """
    return int(os.getenv("SANDAI_OPERATOR_OSS_SIGNED_URL_EXPIRES", "3600"))


def get_storage_type() -> str:
    """
    获取存储类型配置

    环境变量:
        SANDAI_OPERATOR_STORAGE_TYPE: 存储类型 ("minio", "oss", "fake")

    Returns:
        str: 存储类型，默认为 "fake"
    """
    storage_type = os.getenv("SANDAI_OPERATOR_STORAGE_TYPE", "fake").lower()
    print(f"using storage-type: f{storage_type}")
    valid_types = ["minio", "oss", "fake"]

    if storage_type not in valid_types:
        raise ValueError(
            f"Invalid storage type: {storage_type}. Must be one of {valid_types}"
        )

    return storage_type


def get_all_config() -> Dict[str, Any]:
    """
    获取所有配置信息

    Returns:
        Dict[str, Any]: 包含所有配置的字典
    """
    config = {
        "environment": get_environment(),
        "is_development": is_development(),
        "is_production": is_production(),
        "temp_dir": get_temp_dir(),
        "log_level": get_log_level(),
        "max_workers": get_max_workers(),
        "visibility_timeout": get_visibility_timeout(),
        "job_mode_timeout": get_job_mode_timeout(),
        "storage_type": get_storage_type(),
    }

    # MinIO 配置
    minio_config = get_minio_config()
    config["minio"] = {
        "endpoint": minio_config.endpoint,
        "bucket_name": minio_config.bucket_name,
        "region": minio_config.region,
        "prefix": minio_config.prefix,
        "secure": minio_config.secure,
        "is_configured": minio_config.is_configured,
    }

    # OSS 配置
    oss_config = get_oss_config()
    if oss_config:
        config["oss"] = {
            "endpoint": oss_config.endpoint,
            "vpc_endpoint": oss_config.vpc_endpoint,
            "bucket_name": oss_config.bucket_name,
            "region": oss_config.region,
            "prefix": oss_config.prefix,
            "io_via": oss_config.is_configured,
            "has_vpc_endpoint": oss_config.has_vpc_endpoint,
        }
    else:
        config["oss"] = {"is_configured": False, "has_vpc_endpoint": False}

    # Celery 配置
    celery_config = get_celery_config()
    if celery_config:
        config["celery"] = {
            "broker_url": celery_config.broker_url,
            "result_backend": celery_config.result_backend,
            "task_serializer": celery_config.task_serializer,
            "result_serializer": celery_config.result_serializer,
            "is_configured": celery_config.is_configured,
        }
    else:
        # 使用默认配置
        default_celery = get_default_celery_config()
        config["celery"] = {
            "broker_url": default_celery.broker_url,
            "result_backend": default_celery.result_backend,
            "task_serializer": default_celery.task_serializer,
            "result_serializer": default_celery.result_serializer,
            "is_configured": False,  # 标记为使用默认配置
        }

    return config


def print_config_summary():
    """
    打印配置摘要信息（用于调试）
    """
    config = get_all_config()

    print("🔧 Sandai Operator SDK Configuration")
    print("=" * 50)
    print(f"Environment: {config['environment']}")
    print(f"Development Mode: {config['is_development']}")
    print(f"Log Level: {config['log_level']}")
    print(f"Max Workers: {config['max_workers']}")
    print(f"Temp Directory: {config['temp_dir']}")
    print(f"Visibility Timeout: {config['visibility_timeout']}s")
    print(f"Job Mode Timeout: {config['job_mode_timeout']}s")
    print(f"Storage Type: {config['storage_type']}")

    print("\n🗄️  MinIO Configuration:")
    print(f"  Endpoint: {config['minio']['endpoint']}")
    print(f"  Bucket: {config['minio']['bucket_name']}")
    print(f"  Region: {config['minio']['region']}")
    print(f"  Secure: {config['minio']['secure']}")
    print(f"  Prefix: {config['minio']['prefix']}")

    print("\n📦 OSS Configuration:")
    if config["oss"]["is_configured"]:
        print(f"  ✅ Configured")
        print(f"  Bucket: {config['oss']['bucket_name']}")
        print(f"  Region: {config['oss']['region']}")
        print(f"  Prefix: {config['oss']['prefix']}")
        if config["oss"].get("has_vpc_endpoint"):
            print(f"  VPC Endpoint: ✅ Configured")
        else:
            print(f"  VPC Endpoint: ❌ Not configured")
    else:
        print(f"  ❌ Not configured")

    print("\n🔄 Celery Configuration:")
    if config["celery"]["is_configured"]:
        print(f"  ✅ Configured from environment")
    else:
        print(f"  ⚠️  Using default configuration")
    print(f"  Broker: {config['celery']['broker_url']}")
    print(f"  Backend: {config['celery']['result_backend']}")

    print("=" * 50)


if __name__ == "__main__":
    # 运行此模块时打印配置摘要
    print_config_summary()
