import logging
import os
import threading
from importlib.metadata import version
from pathlib import Path
from secrets import token_urlsafe

import tomlkit


class Config:
    _instance = None
    _lock = threading.Lock()
    _initialized = False

    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super(Config, cls).__new__(cls)
                    cls._instance._initialized = False
        return cls._instance

    def __init__(self) -> None:
        if self._initialized:
            return

        self._defaults = {
            "ushka": {"version": version("ushka")},
            "app": {
                "name": "Ushka App",
                "debug": False,
                "auto_discover": True,
                "secret_key": token_urlsafe(128),
            },
            "server": {"host": "127.0.0.1", "port": 8000, "workers": 1},
            "static": {"url": "/static", "folder": "static"},
        }

        self._map_config_to_attributes(self._defaults)
        self._initialized = True
        self.log = logging.getLogger("rich")

    def load_from_file(self, config_path: Path):
        if not os.path.exists(config_path):
            doc = tomlkit.document()
            doc.add(
                tomlkit.comment(
                    f"Configuration Automatically Generated by Ushka 🐱 v{self._defaults['ushka']['version']}"
                )
            )
            doc.update(self._defaults)

            doc.add(tomlkit.nl())

            with open(config_path, "w", encoding="utf-8") as f:
                f.write(tomlkit.dumps(doc))

            self.log.info("🔧 Ushka created a  new ushka.toml")

        with open(config_path, "r", encoding="utf-8") as f:
            doc = tomlkit.parse(f.read())

        for section, keys in self._defaults.items():
            if section == "ushka":
                doc[section] = keys

            if section not in doc:
                doc[section] = keys
            else:
                for key, value in keys.items():
                    if key not in doc[section]:
                        doc[section][key] = value

        with open(config_path, "w", encoding="utf-8") as f:
            f.write(tomlkit.dumps(doc))
            self.log.info("🔧 Ushka touched your ushka.toml")

        self._map_config_to_attributes(doc)
        return doc

    def _map_config_to_attributes(self, data):
        for section, content in data.items():
            if isinstance(content, dict):
                for key, value in content.items():
                    attr_name = f"{section.upper()}_{key.upper()}"
                    setattr(self, attr_name, value)

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