"""Config file loading and path resolution (symlink-safe)."""

from __future__ import annotations

import os
from pathlib import Path

import yaml
from loguru import logger
from pydantic_settings import BaseSettings, SettingsConfigDict

from harvest_session_dbs.config.models import (
    DEFAULT_HOSTS,
    DEFAULT_OUTPUT_DIR,
    DEFAULT_TOOLS,
    HarvestConfig,
)

ENV_CONFIG = "HARVEST_SESSION_DBS_CONFIG"
DEFAULT_FILENAME = "harvest-session-dbs.yaml"


def script_dir() -> Path:
    """Return the real script directory, following symlinks."""
    return Path(os.path.realpath(__file__)).parent


def normalize_config_path(raw: str | Path, default_filename: str) -> Path:
    """Normalize a config path input.

    Args:
        raw: The raw path string or Path object.
        default_filename: Filename to append if raw is a directory.

    Returns:
        A resolved absolute Path.
    """
    p = Path(raw).expanduser()
    if not p.is_absolute():
        p = Path.cwd() / p
    if p.is_dir() or str(raw).endswith(("/", os.sep)):
        p = p / default_filename
    return p


def resolve_config_path(
    cli_opt: str | Path | None,
    *,
    env_var: str,
    default_filename: str,
    default_dir: Path | None = None,
) -> Path:
    """Resolve config path with three-level priority.

    Priority: CLI option > environment variable > default location.

    Args:
        cli_opt: CLI option value, or None.
        env_var: Environment variable name to check.
        default_filename: Default config filename.
        default_dir: Default directory for config file.

    Returns:
        Resolved Path to the config file.
    """
    raw: str | Path | None = cli_opt
    if raw is None:
        raw = os.environ.get(env_var)
    if raw is None:
        base = default_dir if default_dir is not None else Path.cwd()
        return base / default_filename
    return normalize_config_path(raw, default_filename)


def load_config(config_path: Path) -> HarvestConfig:
    """Load configuration from a YAML file, falling back to defaults.

    Args:
        config_path: Path to the YAML config file.

    Returns:
        A HarvestConfig instance.
    """
    if not config_path.exists():
        logger.debug(f"Config file not found at {config_path}, using defaults")
        return HarvestConfig(
            hosts=list(DEFAULT_HOSTS),
            tools=list(DEFAULT_TOOLS),
        )
    with config_path.open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    return HarvestConfig(**data)


class HarvestSettings(BaseSettings):
    """Settings from environment variables.

    Attributes:
        output_dir: Default fixture output directory.
    """

    model_config = SettingsConfigDict(
        env_prefix="HARVEST_SESSION_DBS_",
        env_file_encoding="utf-8",
    )
    output_dir: Path = DEFAULT_OUTPUT_DIR
