"""Config template and source annotation utilities.

Provides CONFIG_TEMPLATE for ``policyfoundry init`` and source annotation
utilities for ``policyfoundry config show``.
"""

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from typing import TYPE_CHECKING, Any, cast

import yaml

if TYPE_CHECKING:
    from pathlib import Path

from policyfoundry.config.models import PolicyFoundryConfig


class ConfigSource(Enum):
    """Identifies where a config value originated."""

    DEFAULT = "default"
    GLOBAL_YAML = "~/.policyfoundry/config.yaml"
    LOCAL_YAML = ".policyfoundry.yaml"
    ENV_VAR = "env"
    CLI_FLAG = "--config"


@dataclass
class AnnotatedValue:
    """A config value annotated with its source."""

    value: object
    source: ConfigSource
    key: str


CONFIG_TEMPLATE = """\
# PolicyFoundry Configuration
# Generated by: policyfoundry init
# Docs: https://github.com/policyfoundry/policyfoundry

# LLM Provider Settings
llm:
  # Provider: ollama | bedrock | openai
  provider: ollama
  # Model name or ID
  model: llama3.2
  # Temperature for analysis consistency (lower = more deterministic)
  # temperature: 0.1
  # Max tokens per LLM call
  # max_tokens: 4096
  # Custom API endpoint (for self-hosted or proxy)
  # base_url: null
  # API key (prefer env var POLICYFOUNDRY_LLM__API_KEY instead)
  # api_key: null
  # Request timeout in seconds
  # timeout: 120

# Log Sources
sources:
  # Local log file paths (glob patterns supported)
  # log_paths:
  #   - /var/log/vpc-flow/*.log
  #   - ./logs/**/*.log.gz
  # S3 bucket for remote logs
  # s3_bucket: my-vpc-logs-bucket
  # S3 key prefix filter
  # s3_prefix: vpc-flow-logs/
  # AWS profile for S3 access
  # aws_profile: default

# Target Security Groups
targets:
  # Security Group IDs to analyze
  # security_group_ids:
  #   - sg-0123456789abcdef0

# Output Settings
output:
  # Output format: rich (terminal) | json (machine-readable)
  format: rich
"""


def _flatten_config(config: PolicyFoundryConfig) -> dict[str, object]:
    """Flatten a config into dotted-key -> value pairs."""
    result: dict[str, object] = {}
    data = config.model_dump()
    for section, values in data.items():
        if isinstance(values, dict):
            for key in cast("dict[str, object]", values):
                result[f"{section}.{key}"] = values[key]
        else:
            result[section] = values
    return result


def _load_yaml_flat(yaml_path: Path) -> dict[str, object]:
    """Load a YAML file and return flattened dotted-key dict."""
    if not yaml_path.exists():
        return {}
    with yaml_path.open() as f:
        data = yaml.safe_load(f)

    if not isinstance(data, dict):
        return {}

    typed_data = cast("dict[str, object]", data)
    result: dict[str, object] = {}
    for section, values in typed_data.items():
        if isinstance(values, dict):
            section_vals = cast(
                "dict[str, object]", values
            )
            for key, val in section_vals.items():
                result[f"{section}.{key}"] = val
        else:
            result[section] = values
    return result


def resolve_with_annotations(
    config: PolicyFoundryConfig,
    global_yaml_path: Path | None = None,
    local_yaml_path: Path | None = None,
) -> dict[str, AnnotatedValue]:
    """Resolve config and annotate each value with its source.

    Determines which source provided each config value by comparing
    against YAML files and defaults.
    """
    flat = _flatten_config(config)

    global_vals: dict[str, object] = {}
    if global_yaml_path is not None:
        global_vals = _load_yaml_flat(global_yaml_path)

    local_vals: dict[str, object] = {}
    if local_yaml_path is not None:
        local_vals = _load_yaml_flat(local_yaml_path)

    default_flat = _flatten_config(PolicyFoundryConfig())

    annotations: dict[str, AnnotatedValue] = {}
    for key, value in flat.items():
        if key in local_vals and value == local_vals[key]:
            if value != default_flat.get(key) or key in local_vals:
                source = ConfigSource.LOCAL_YAML
            else:
                source = ConfigSource.DEFAULT
        elif key in global_vals and value == global_vals[key]:
            source = ConfigSource.GLOBAL_YAML
        elif value != default_flat.get(key):
            source = ConfigSource.ENV_VAR
        else:
            source = ConfigSource.DEFAULT

        annotations[key] = AnnotatedValue(
            value=value, source=source, key=key
        )

    return annotations
