# -*- coding: utf-8 -*-
import os
from typing import Any, Optional

from langchain_core.runnables import RunnableConfig
from pydantic import BaseModel, Field


class Configuration(BaseModel):
    """The configuration for the agent."""

    query_generator_model: str = Field(
        default="qwen-max-latest",
        metadata={
            "description": "The name of the language model to use for "
            "the agent's query generation.",
        },
    )
    query_generator_param: dict = Field(
        default={"temperature": 0.3, "stream": False},
    )

    reflection_model: str = Field(
        default="qwen-plus-latest",
        metadata={
            "description": "The name of the language model to use for"
            " the agent's reflection.",
        },
    )
    reflection_param: dict = Field(
        default={"temperature": 0.3, "stream": False},
    )

    answer_model: str = Field(
        default="qwen-plus-latest",
        metadata={
            "description": "The name of the language model to use "
            "for the agent's answer.",
        },
    )
    answer_param: dict = Field(default={"temperature": 0.3, "stream": False})

    num_of_init_q: int = Field(
        default=3,
        metadata={
            "description": "The number of initial search queries to generate.",
        },
    )

    max_research_loops: int = Field(
        default=2,
        metadata={
            "description": "The maximum number of research loops to perform.",
        },
    )

    @classmethod
    def from_runnable_config(
        cls,
        config: Optional[RunnableConfig] = None,
    ) -> "Configuration":
        """Create a Configuration instance from a RunnableConfig."""
        configurable = (
            config["configurable"]
            if config and "configurable" in config
            else {}
        )

        # Get raw values from environment or config
        raw_values: dict[str, Any] = {
            name: os.environ.get(name.upper(), configurable.get(name))
            for name in cls.model_fields.keys()
        }

        # Filter out None values
        values = {k: v for k, v in raw_values.items() if v is not None}

        return cls(**values)
