"""SDK configuration via pydantic-settings, with per-target config models."""

from __future__ import annotations

import os
from typing import Literal

import structlog
from pydantic import SecretStr
from pydantic_settings import BaseSettings

S3Partition = Literal["none", "year", "month", "day", "hour"]

logger = structlog.get_logger()

# Shared fields across all targets
_BASE_FIELDS = {
    "flush_interval",
    "batch_size",
    "max_queue_size",
    "max_retries",
    "capture_tools",
    "patch_anthropic",
    "patch_openai",
    "debug",
}


class BaseConfig(BaseSettings):
    """Fields shared by every export target."""

    model_config = {"env_prefix": "CALIPER_"}

    flush_interval: float = 2.0
    batch_size: int = 250
    max_queue_size: int = 10_000
    max_retries: int = 3
    capture_tools: bool = False
    patch_anthropic: bool = True
    patch_openai: bool = True
    debug: bool = False


class DevConfig(BaseConfig):
    """Config for the local-file dev target."""

    file_path: str = "caliper_records.jsonl"
    annotations_file_path: str | None = None


class S3Config(BaseConfig):
    """Config for the S3 export target."""

    s3_bucket: str | None = None
    s3_prefix: str = ""
    s3_region: str = "us-east-1"
    s3_access_key: str | None = None
    s3_secret_key: SecretStr | None = None
    s3_endpoint: str | None = None
    s3_partition: S3Partition = "hour"


TARGET_CONFIGS: dict[str, type[BaseConfig]] = {
    "dev": DevConfig,
    "s3": S3Config,
}


def build_config(target: str, **explicit_kwargs) -> BaseConfig:
    """Build the right config model for the given target.

    Env vars (CALIPER_*) take highest priority, then kwargs passed here,
    then pydantic defaults. This lets ops teams override settings at runtime
    without code changes.
    """
    config_cls = TARGET_CONFIGS.get(target)
    if config_cls is None:
        raise ValueError(
            f"Unknown export target: {target!r}. Valid targets: {', '.join(repr(t) for t in TARGET_CONFIGS)}"
        )

    valid_fields = set(config_cls.model_fields.keys())
    env_prefix = config_cls.model_config.get("env_prefix", "")

    # Only forward a kwarg when its corresponding env var is not set.
    filtered_kwargs = {}
    for key, value in explicit_kwargs.items():
        if key not in valid_fields:
            logger.warning("caliper.config.unknown_kwarg", target=target, kwarg=key)
            continue
        env_var = f"{env_prefix}{key}".upper()
        if os.environ.get(env_var) is None:
            filtered_kwargs[key] = value

    return config_cls(**filtered_kwargs)
