from functools import lru_cache
from typing import Literal

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


class Settings(BaseSettings):
    app_name: str = Field(default="MacroBase Freshchat API", alias="APP_NAME")
    app_env: str = Field(default="development", alias="APP_ENV")
    freshchat_api_token: str = Field(default="change-me", alias="FRESHCHAT_API_TOKEN")
    default_response_mode: Literal["internal", "freshchat_simple", "fallback"] = Field(
        default="freshchat_simple",
        alias="DEFAULT_RESPONSE_MODE",
    )
    freshworks_api_base_url: str | None = Field(default=None, alias="FRESHWORKS_API_BASE_URL")
    freshworks_api_token: str | None = Field(default=None, alias="FRESHWORKS_API_TOKEN")
    freshworks_default_actor_type: Literal["agent", "bot"] = Field(
        default="bot",
        alias="FRESHWORKS_DEFAULT_ACTOR_TYPE",
    )
    freshworks_default_actor_id: str | None = Field(default=None, alias="FRESHWORKS_DEFAULT_ACTOR_ID")
    freshworks_assume_identity: bool = Field(default=False, alias="FRESHWORKS_ASSUME_IDENTITY")
    event_store_path: str = Field(default="data/freshchat_events.db", alias="EVENT_STORE_PATH")
    customer_state_backend: Literal["sqlite", "mysql"] = Field(
        default="sqlite",
        alias="CUSTOMER_STATE_BACKEND",
    )
    customer_state_store_path: str = Field(
        default="data/customer_state.db",
        alias="CUSTOMER_STATE_STORE_PATH",
    )
    customer_state_mysql_host: str | None = Field(default=None, alias="CUSTOMER_STATE_MYSQL_HOST")
    customer_state_mysql_port: int = Field(default=3306, alias="CUSTOMER_STATE_MYSQL_PORT")
    customer_state_mysql_database: str | None = Field(default=None, alias="CUSTOMER_STATE_MYSQL_DATABASE")
    customer_state_mysql_user: str | None = Field(default=None, alias="CUSTOMER_STATE_MYSQL_USER")
    customer_state_mysql_password: str | None = Field(default=None, alias="CUSTOMER_STATE_MYSQL_PASSWORD")
    customer_state_mysql_table: str = Field(default="customer_states", alias="CUSTOMER_STATE_MYSQL_TABLE")
    freshchat_webhook_verify_signature: bool = Field(
        default=False,
        alias="FRESHCHAT_WEBHOOK_VERIFY_SIGNATURE",
    )
    freshchat_api_base_url: str | None = Field(default=None, alias="FRESHCHAT_API_BASE_URL")
    freshchat_auto_reply_enabled: bool = Field(default=False, alias="FRESHCHAT_AUTO_REPLY_ENABLED")
    freshchat_send_as_actor_type: Literal["agent", "bot", "user"] = Field(
        default="bot",
        alias="FRESHCHAT_SEND_AS_ACTOR_TYPE",
    )

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

    @model_validator(mode="after")
    def validate_freshchat_auto_reply_config(self) -> "Settings":
        if not self.freshchat_auto_reply_enabled:
            return self

        if not self.freshchat_api_base_url:
            raise ValueError("FRESHCHAT_API_BASE_URL es requerido si FRESHCHAT_AUTO_REPLY_ENABLED=true.")

        if not self.freshchat_api_token or self.freshchat_api_token == "change-me":
            raise ValueError("FRESHCHAT_API_TOKEN es requerido si FRESHCHAT_AUTO_REPLY_ENABLED=true.")

        if self.customer_state_backend == "mysql":
            missing = []
            if not self.customer_state_mysql_host:
                missing.append("CUSTOMER_STATE_MYSQL_HOST")
            if not self.customer_state_mysql_database:
                missing.append("CUSTOMER_STATE_MYSQL_DATABASE")
            if not self.customer_state_mysql_user:
                missing.append("CUSTOMER_STATE_MYSQL_USER")
            if self.customer_state_mysql_password is None:
                missing.append("CUSTOMER_STATE_MYSQL_PASSWORD")
            if missing:
                raise ValueError(
                    "Faltan variables para CUSTOMER_STATE_BACKEND=mysql: " + ", ".join(missing)
                )

        return self


@lru_cache
def get_settings() -> Settings:
    return Settings()
