from __future__ import annotations

from functools import lru_cache
from pathlib import Path
from typing import Self

from pydantic import Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

from supply_agent.paths import resolve_path


class Settings(BaseSettings):
    """Application settings loaded from environment variables or .env file."""

    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )

    # OpenRouter
    openrouter_api_key: str = Field(..., alias="OPENROUTER_API_KEY")
    openrouter_model: str = Field(
        default="google/gemini-2.5-flash",
        alias="OPENROUTER_MODEL",
    )
    openrouter_base_url: str = Field(
        default="https://openrouter.ai/api/v1",
        alias="OPENROUTER_BASE_URL",
    )
    openrouter_site_url: str = Field(default="", alias="OPENROUTER_SITE_URL")
    openrouter_site_name: str = Field(default="SupplyAgent", alias="OPENROUTER_SITE_NAME")
    openrouter_timeout_seconds: float = Field(
        default=120.0,
        alias="OPENROUTER_TIMEOUT_SECONDS",
    )

    # Agent
    agent_max_iterations: int = Field(default=20, alias="AGENT_MAX_ITERATIONS")
    agent_temperature: float = Field(default=0.7, alias="AGENT_TEMPERATURE")

    # Skills
    skills_dir: Path = Field(default=Path("skills"), alias="SKILLS_DIR")

    # Logging
    logs_dir: Path = Field(default=Path("logs"), alias="LOGS_DIR")
    log_enabled: bool = Field(default=True, alias="LOG_ENABLED")

    @model_validator(mode="after")
    def resolve_relative_paths(self) -> Self:
        """Resolve skills_dir and logs_dir against project root when needed."""
        self.skills_dir = resolve_path(self.skills_dir)
        self.logs_dir = resolve_path(self.logs_dir)
        return self

    @classmethod
    def from_env(cls, **overrides: object) -> Self:
        """Create settings with optional overrides (useful for testing)."""
        return cls(**overrides)  # type: ignore[arg-type]


@lru_cache
def get_settings() -> Settings:
    return Settings()  # type: ignore[call-arg]
