import os
from pathlib import Path
from typing import Any, Dict, List, Optional
from annotatedyaml.loader import (
    HAS_C_LOADER,
    JSON_TYPE,
    LoaderType,
    Secrets,
    add_constructor,
    load_yaml as load_annotated_yaml,
    load_yaml_dict as load_annotated_yaml_dict,
    parse_yaml as parse_annotated_yaml,
    secret_yaml as annotated_secret_yaml,
)
from voluptuous import Schema, Required, All, Length, PREVENT_EXTRA, MultipleInvalid

# --- Voluptuous schemas ---
database_schema = Schema({Required("url"): str}, extra=PREVENT_EXTRA)


hotel_auth_schema = Schema(
    {
        Required("hotel_id"): str,
        Required("hotel_name"): str,
        Required("username"): str,
        Required("password"): str,
    },
    extra=PREVENT_EXTRA,
)

basic_auth_schema = Schema(All([hotel_auth_schema], Length(min=1)))

config_schema = Schema(
    {
        Required("database"): database_schema,
        Required("alpine_bits_auth"): basic_auth_schema,
    },
    extra=PREVENT_EXTRA,
)

DEFAULT_CONFIG_FILE = "config.yaml"


class Config:
    def __init__(
        self,
        config_folder: str | Path = None,
        config_name: str = DEFAULT_CONFIG_FILE,
        testing_mode: bool = False,
    ):
        if config_folder is None:
            config_folder = os.environ.get("ALPINEBITS_CONFIG_DIR")
            if not config_folder:
                config_folder = os.path.abspath(
                    os.path.join(os.path.dirname(__file__), "../../config")
                )
        if isinstance(config_folder, str):
            config_folder = Path(config_folder)
        self.config_folder = config_folder
        self.config_path = os.path.join(config_folder, config_name)
        self.secrets = Secrets(config_folder)
        self.testing_mode = testing_mode
        self._load_config()

    def _load_config(self):
        stuff = load_annotated_yaml(self.config_path, secrets=self.secrets)
        try:
            validated = config_schema(stuff)
        except MultipleInvalid as e:
            raise ValueError(f"Config validation error: {e}")
        self.database = validated["database"]
        self.basic_auth = validated["alpine_bits_auth"]
        self.config = validated

    def get(self, key, default=None):
        return self.config.get(key, default)

    @property
    def db_url(self) -> str:
        return self.database["url"]

    @property
    def hotel_id(self) -> str:
        return self.basic_auth["hotel_id"]

    @property
    def hotel_name(self) -> str:
        return self.basic_auth["hotel_name"]

    @property
    def users(self) -> List[Dict[str, str]]:
        return self.basic_auth["users"]


# For backward compatibility
def load_config():
    return Config().config
