"""
Elasticsearch 连接配置与安全配置。
支持 ES_HOSTS 单 URL（如 https://host:9200），或 ES_HOST/ES_PORT/ES_USER/ES_PASSWORD；
多环境可用 TEST_ES_PROFILES / UAT_ES_PROFILES / PROD_ES_PROFILES（JSON 内可用 hosts、username、pwd）。
"""
from __future__ import annotations

import os
import sys
import json
from dataclasses import dataclass
from urllib.parse import urlparse


@dataclass
class ConnectionConfig:
    """单条 ES 连接配置"""
    host: str
    port: int
    user: str = ""
    password: str = ""
    use_ssl: bool = False
    description: str | None = None
    skip_product_check: bool = False  # True 时跳过 X-Elastic-Product 校验（兼容 OpenSearch/自建）


@dataclass
class SafetyConfig:
    """安全与行为配置"""
    read_only: bool = False
    max_search_size: int = 100
    request_timeout: 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 _parse_hosts_url(url: str) -> tuple[str, int, bool]:
    """从 ES_HOSTS 或 profile.hosts 解析 host, port, use_ssl。例如 https://es.example.com:9200"""
    s = (url or "").strip()
    if not s:
        return "", 9200, False
    if "://" not in s:
        s = "http://" + s
    p = urlparse(s)
    host = (p.hostname or p.netloc or "").strip()
    port = p.port if p.port is not None else 9200
    use_ssl = (p.scheme or "").lower() == "https"
    return host, port, use_ssl


def load_safety_config() -> SafetyConfig:
    return SafetyConfig(
        read_only=_parse_bool(os.environ.get("ES_READ_ONLY")),
        max_search_size=_parse_int(os.environ.get("ES_MAX_SEARCH_SIZE"), 100),
        request_timeout=_parse_int(os.environ.get("ES_REQUEST_TIMEOUT"), 30),
    )


def load_connection_map() -> tuple[ConnectionConfig, dict[str, ConnectionConfig], str]:
    """优先 TEST_ES_PROFILES / UAT_ES_PROFILES / PROD_ES_PROFILES；否则 ES_HOST/ES_PORT/ES_USER/ES_PASSWORD。"""
    connection_map: dict[str, ConnectionConfig] = {}
    default_profile_name = "default"
    default: ConnectionConfig | None = None

    for env in ("test", "uat", "prod"):
        key = f"{env.upper()}_ES_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
                hosts_url = (v.get("hosts") or "").strip()
                if hosts_url:
                    host, port, use_ssl = _parse_hosts_url(hosts_url)
                else:
                    host = str(v.get("host", "")).strip()
                    port = _parse_int(v.get("port"), 9200)
                    use_ssl = _parse_bool(v.get("use_ssl")) if v.get("use_ssl") is not None else (str(v.get("use_ssl", "")).strip().lower() == "true")
                if not host:
                    continue
                user = str(v.get("user") or v.get("username", "") or "").strip()
                password = str(v.get("password") or v.get("pwd", "") or "")
                desc = v.get("description")
                description = (str(desc).strip() or None) if desc is not None else None
                skip_product_check = _parse_bool(v.get("skip_product_check"))
                conn = ConnectionConfig(
                    host=host,
                    port=port,
                    user=user,
                    password=password,
                    use_ssl=use_ssl,
                    description=description,
                    skip_product_check=skip_product_check,
                )
                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_")]
        default_profile_name = prod_keys[0] if prod_keys else next(iter(connection_map))
        default = connection_map[default_profile_name]
        return default, connection_map, default_profile_name

    hosts_url = os.environ.get("ES_HOSTS", "").strip()
    if hosts_url:
        host, port, use_ssl = _parse_hosts_url(hosts_url)
    else:
        host = os.environ.get("ES_HOST", "").strip()
        port = _parse_int(os.environ.get("ES_PORT"), 9200)
        use_ssl = _parse_bool(os.environ.get("ES_USE_SSL"))
    user = os.environ.get("ES_USER") or os.environ.get("ES_USERNAME", "") or ""
    user = str(user).strip()
    password = os.environ.get("ES_PASSWORD") or os.environ.get("ES_PWD", "") or ""
    password = str(password)
    skip_product_check = _parse_bool(os.environ.get("ES_SKIP_PRODUCT_CHECK"))
    if not host:
        print("错误: 缺少 ES_HOST 或 ES_HOSTS。多环境请配置 TEST_ES_PROFILES / UAT_ES_PROFILES / PROD_ES_PROFILES", file=sys.stderr)
        sys.exit(1)
    default = ConnectionConfig(
        host=host, port=port, user=user, password=password, use_ssl=use_ssl,
        description=None, skip_product_check=skip_product_check,
    )
    connection_map["default"] = default
    return default, connection_map, "default"
