from typing import Literal
from typing_extensions import Self
from pydantic import MySQLDsn, PostgresDsn, SecretStr, ValidationError
from pydantic_settings import BaseSettings
from takk.secrets import LLMBaseAPI, LLMToken, TakkLlmModels


class SettingsModel(BaseSettings):
    
    @classmethod
    def from_env(cls: type[Self]) -> Self:
        key = "__settings_cache__"

        if key not in cls.__dict__:
            setattr(cls, key, cls()) # type: ignore[call-arg]

        return getattr(cls, key)

    @classmethod
    def from_env_or_none(cls: type[Self]) -> Self | None:
        try:
            return cls.from_env()
        except ValidationError:
            return None


class PostgresSettings(SettingsModel):
    db_uri: PostgresDsn

class MysqlSettings(SettingsModel):
    db_uri: MySQLDsn

class MaurSettings(SettingsModel):
    maur_bearer_token: SecretStr


class GitlabSettings(SettingsModel):
    gitlab_repo_url: str
    gitlab_token: SecretStr
    gitlab_url: str = "https://gitlab.com"


class GithubSettings(SettingsModel):
    github_repo_url: str
    github_token: SecretStr
    github_api_url: str = "https://api.github.com"


class MaurLLMSettings(SettingsModel):
    maur_llm_token: LLMToken
    maur_llm_api: LLMBaseAPI

    maur_llm_model: TakkLlmModels | str = "qwen3.5:4b"


def db_setting_type(db_type: Literal["psql", "mysql"]) -> type[PostgresSettings] | type[MysqlSettings]:
    return {
        "psql": PostgresSettings,
        "mysql": MysqlSettings
    }[db_type]
