from pathlib import Path
from typing import Any, Tuple, Type

import yaml
from pydantic_settings import BaseSettings, InitSettingsSource, PydanticBaseSettingsSource, SettingsConfigDict
from pydantic_settings.sources import ConfigFileSourceMixin, EnvSettingsSource


def parse_cors(v: Any) -> list[str] | str:
    if isinstance(v, str) and not v.startswith("["):
        return [i.strip() for i in v.split(",")]
    elif isinstance(v, list | str):
        return v
    raise ValueError(v)


class ProjectBaseSettings(BaseSettings):
    model_config = SettingsConfigDict(yaml_file="envs.yml", yaml_file_encoding="utf-8", env_prefix="service")

    @classmethod
    def settings_customise_sources(
        cls,
        settings_cls: Type[BaseSettings],
        init_settings: PydanticBaseSettingsSource,
        env_settings: EnvSettingsSource,  # type: ignore
        dotenv_settings: PydanticBaseSettingsSource,
        file_secret_settings: PydanticBaseSettingsSource,
    ) -> Tuple[PydanticBaseSettingsSource, ...]:
        return (
            init_settings,
            PrefixedYamlConfigSettingsSource(env_settings.env_prefix, settings_cls),
            env_settings,
            file_secret_settings,
        )


class PrefixedYamlConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
    def __init__(self, prefix: str, settings_cls: type[BaseSettings]):
        self.yaml_file_path = "envs.yml"
        self.yaml_file_encoding = "utf-8"
        self.yaml_data = self._read_files(self.yaml_file_path)[prefix]
        super().__init__(settings_cls, self.yaml_data)

    def _read_file(self, file_path: Path) -> dict[str, dict[str, Any]]:
        with open(file_path, encoding=self.yaml_file_encoding) as yaml_file:
            return yaml.safe_load(yaml_file)
