"""
配置加载：Redis 连接（单机/集群）、安全与行为配置。
"""
from __future__ import annotations

import os
import sys
import json
from dataclasses import dataclass
from typing import Literal


@dataclass
class ConnectionConfig:
    """单条 Redis 连接配置"""
    mode: Literal["standalone", "cluster"]
    host: str
    port: int
    password: str = ""
    db: int = 0
    description: str | None = None
    # 集群时使用，standalone 忽略
    hosts: list[str] | None = None  # ["host1:6379", "host2:6379"]


@dataclass
class SafetyConfig:
    """安全与行为配置（全局）"""
    read_only: bool = False
    max_scan_keys: int = 1000  # SCAN 单次最多返回 key 数量
    confirm_dangerous: bool = True  # 危险命令需 confirm
    command_timeout_seconds: int = 30


def _parse_bool(val: str | None) -> bool:
    if val is None:
        return False
    return str(val).strip().lower() in ("1", "true", "yes", "on")


def _parse_int(val: str | int | None, default: int) -> int:
    if val is None:
        return default
    if isinstance(val, int):
        return val
    try:
        return int((val or "").strip())
    except (ValueError, AttributeError):
        return default


def load_safety_config() -> SafetyConfig:
    """从环境变量加载安全配置"""
    return SafetyConfig(
        read_only=_parse_bool(os.environ.get("REDIS_READ_ONLY")),
        max_scan_keys=_parse_int(os.environ.get("REDIS_MAX_SCAN_KEYS"), 1000),
        confirm_dangerous=_parse_bool(os.environ.get("REDIS_CONFIRM_DANGEROUS")) or True,
        command_timeout_seconds=_parse_int(os.environ.get("REDIS_COMMAND_TIMEOUT_SECONDS"), 30),
    )


def load_connection_map() -> tuple[ConnectionConfig, dict[str, ConnectionConfig], str]:
    """
    加载 Redis 连接配置。
    优先: TEST_REDIS_PROFILES / UAT_REDIS_PROFILES / PROD_REDIS_PROFILES（JSON 数组）。
    否则: REDIS_HOST, REDIS_PORT, REDIS_PASSWORD 单连接。
    返回: (default_connection, connection_map, default_profile_name)
    """
    connection_map: dict[str, ConnectionConfig] = {}
    default_profile_name = "default"
    default: ConnectionConfig | None = None

    # 优先: 按环境的数组
    for env in ("test", "uat", "prod"):
        key = f"{env.upper()}_REDIS_PROFILES"
        arr_json = os.environ.get(key)
        if not arr_json:
            continue
        try:
            arr = json.loads(arr_json)
            if not isinstance(arr, list):
                continue
            for i, v in enumerate(arr):
                if not isinstance(v, dict):
                    continue
                mode = (v.get("mode") or "standalone")
                if mode not in ("standalone", "cluster"):
                    mode = "standalone"
                password = str(v.get("password", "") or "")
                desc = v.get("description")
                description = (str(desc).strip() or None) if desc is not None else None
                port = _parse_int(v.get("port"), 6379)
                db = _parse_int(v.get("db"), 0)
                if mode == "standalone":
                    host = str(v.get("host", "")).strip()
                    if not host:
                        continue
                    conn = ConnectionConfig(
                        mode="standalone",
                        host=host,
                        port=port,
                        password=password,
                        db=db,
                        description=description,
                        hosts=None,
                    )
                else:
                    hosts_val = v.get("hosts")
                    if isinstance(hosts_val, list) and hosts_val:
                        hosts = [str(h).strip() for h in hosts_val if h]
                    else:
                        host = str(v.get("host", "")).strip()
                        if host:
                            hosts = [f"{host}:{port}"]
                        else:
                            continue
                    if not hosts:
                        continue
                    conn = ConnectionConfig(
                        mode="cluster",
                        host=hosts[0].split(":")[0] if ":" in hosts[0] else hosts[0],
                        port=port,
                        password=password,
                        db=0,
                        description=description,
                        hosts=hosts,
                    )
                sub_name = (v.get("name") or "").strip() or str(i)
                profile_key = f"{env}_{sub_name}" if sub_name != str(i) else f"{env}_{i}"
                connection_map[profile_key] = conn
        except json.JSONDecodeError:
            pass

    if connection_map:
        prod_keys = [k for k in connection_map if k.startswith("prod_")]
        if prod_keys:
            default_profile_name = prod_keys[0]
            default = connection_map[default_profile_name]
        else:
            default_profile_name = next(iter(connection_map))
            default = connection_map[default_profile_name]
        return default, connection_map, default_profile_name

    # 单连接
    host = os.environ.get("REDIS_HOST", "").strip()
    port = _parse_int(os.environ.get("REDIS_PORT"), 6379)
    password = os.environ.get("REDIS_PASSWORD", "")
    db = _parse_int(os.environ.get("REDIS_DB"), 0)
    if not host:
        print(
            "错误: 缺少 REDIS_HOST。多环境请配置 TEST_REDIS_PROFILES / UAT_REDIS_PROFILES / PROD_REDIS_PROFILES",
            file=sys.stderr,
        )
        sys.exit(1)
    default = ConnectionConfig(
        mode="standalone",
        host=host,
        port=port,
        password=password or "",
        db=db,
        description=None,
        hosts=None,
    )
    connection_map["default"] = default
    default_profile_name = "default"
    return default, connection_map, default_profile_name
