"""Configuration management for CVEasy."""

import os
from pathlib import Path
from typing import Optional

# Track if we've loaded the .env file from project root
_env_loaded_from_project = False

# Cache for project root to avoid repeated filesystem traversal
_project_root_cache: Optional[Path] = None
_project_root_cache_path: Optional[Path] = None


def _load_env_from_project_root():
    """Load .env file from project root if it exists."""
    global _env_loaded_from_project
    if _env_loaded_from_project:
        return

    try:
        from dotenv import load_dotenv
    except ImportError:
        return  # python-dotenv not installed, skip

    # Try to find project root and load .env from there
    project_root = find_project_root()
    if project_root:
        env_file = project_root / ".env"
        if env_file.exists():
            load_dotenv(env_file, override=True)
            _env_loaded_from_project = True
            return

    # If no project root found, search up the directory tree for .env
    current = Path.cwd().resolve()
    for path in [current] + list(current.parents):
        env_file = path / ".env"
        if env_file.exists():
            load_dotenv(env_file, override=True)
            _env_loaded_from_project = True
            return

    # Fallback: try current directory (default behavior)
    load_dotenv()
    _env_loaded_from_project = True


# Removed eager loading - now only loads when _load_env_from_project_root() is called


def find_project_root(start_path: Optional[Path] = None) -> Optional[Path]:
    """
    Find the project root directory by looking for .git directory or resume subdirectories.

    Uses caching to avoid repeated filesystem traversal.

    Args:
        start_path: Starting path for search. Defaults to current working directory.

    Returns:
        Path to project root if found, None otherwise.
    """
    global _project_root_cache, _project_root_cache_path

    if start_path is None:
        start_path = Path.cwd()

    start_path = Path(start_path).resolve()

    # Check cache first
    if _project_root_cache is not None and _project_root_cache_path == start_path:
        return _project_root_cache

    current = start_path

    # Check if we're in a project directory
    for path in [current] + list(current.parents):
        # Check for .git directory
        if (path / ".git").exists():
            # Verify it has the expected structure
            if all(
                (path / subdir).exists()
                for subdir in [
                    "skills",
                    "experiences",
                    "stories",
                    "links",
                    "projects",
                    "applications",
                ]
            ):
                _project_root_cache = path
                _project_root_cache_path = start_path
                return path

        # Also check for expected subdirectories without .git
        if all(
            (path / subdir).exists()
            for subdir in ["skills", "experiences", "stories", "links", "projects", "applications"]
        ):
            _project_root_cache = path
            _project_root_cache_path = start_path
            return path

    # Cache None result too
    _project_root_cache = None
    _project_root_cache_path = start_path
    return None


def get_project_path(project_path: Optional[str] = None) -> Path:
    """
    Get the project path, either from argument or by finding it.

    Args:
        project_path: Explicit project path from --project flag.

    Returns:
        Path to project root.

    Raises:
        ValueError: If project path cannot be determined.
    """
    if project_path:
        path = Path(project_path).resolve()
        if not path.exists():
            raise ValueError(f"Project path does not exist: {project_path}")
        return path

    found = find_project_root()
    if found is None:
        raise ValueError(
            "Not in a CVEasy project directory. Run 'cveasy init' first or use --project flag."
        )
    return found


def get_ai_provider() -> str:
    """
    Get the configured AI provider from environment variables.

    Returns:
        The AI provider name (openai, anthropic, or openrouter)

    Raises:
        ValueError: If CVEASY_AI_PROVIDER is not set in environment variables or .env file
    """
    # Ensure .env file is loaded from project root
    _load_env_from_project_root()
    provider = os.getenv("CVEASY_AI_PROVIDER")

    # Check if the environment variable is not set at all
    if provider is None:
        raise ValueError(
            "CVEASY_AI_PROVIDER environment variable is not set. "
            "Please configure your .env file with:\n"
            "  CVEASY_AI_PROVIDER=openai  # or 'anthropic' or 'openrouter'\n"
            "  CVEASY_API_KEY=your_key_here\n"
            "\n"
            "You can use 'cveasy config' to configure interactively, or copy .env.example to .env and update it."
        )

    # Normalize to lowercase for case-insensitive matching
    provider = provider.lower().strip()

    # Check if the environment variable is set but empty (after stripping whitespace)
    if not provider:
        raise ValueError(
            "CVEASY_AI_PROVIDER is set but empty. "
            "Please set it to one of: openai, anthropic, or openrouter"
        )

    return provider


def get_openai_api_key() -> Optional[str]:
    """Get OpenAI API key from environment variables."""
    _load_env_from_project_root()
    return os.getenv("OPENAI_API_KEY")


def get_anthropic_api_key() -> Optional[str]:
    """Get Anthropic API key from environment variables."""
    _load_env_from_project_root()
    return os.getenv("ANTHROPIC_API_KEY")


def get_openrouter_api_key() -> Optional[str]:
    """Get OpenRouter API key from environment variables."""
    _load_env_from_project_root()
    return os.getenv("OPENROUTER_API_KEY")


def get_cveasy_api_key() -> Optional[str]:
    """Get unified API key from environment variables."""
    _load_env_from_project_root()
    return os.getenv("CVEASY_API_KEY")


def get_cveasy_model() -> Optional[str]:
    """Get unified model name from environment variables."""
    _load_env_from_project_root()
    return os.getenv("CVEASY_MODEL")


def get_cveasy_max_tokens() -> int:
    """Get unified max tokens from environment variables."""
    _load_env_from_project_root()
    max_tokens = os.getenv("CVEASY_MAX_TOKENS", "8192")
    try:
        return int(max_tokens)
    except ValueError:
        return 8192  # Default if invalid value


def get_spacy_model() -> str:
    """Get spaCy model name. Always returns en_core_web_sm (hard-coded)."""
    return "en_core_web_sm"
