import os
from pathlib import Path
from typing import Optional

import yaml
from src.utilities.misc_helper import current_system_os, copy_directory_contents

_CONFIG_ATTRS = [
    'upload_folder', 'update_engines_on_launch', 'max_content_path',
    'server_log_level', 'log_buffer_length', 'worker_process_timeout',
    'flask_log_level', 'flask_debug_enable', 'queue_eval_seconds',
    'port_number', 'enable_split_jobs', 'download_timeout_seconds',
]


class Config:
    _default_instance: Optional['Config'] = None

    # Class-level defaults — mutated by _sync_class() so existing
    # callers (Config.upload_folder) continue to work during the
    # migration to instance-based access.
    upload_folder = "~/zordon-uploads/"
    update_engines_on_launch = True
    max_content_path = 100000000
    server_log_level = 'debug'
    log_buffer_length = 250
    worker_process_timeout = 120
    flask_log_level = 'error'
    flask_debug_enable = False
    queue_eval_seconds = 1
    port_number = 8080
    enable_split_jobs = True
    download_timeout_seconds = 120

    def __init__(self) -> None:
        for attr in _CONFIG_ATTRS:
            setattr(self, attr, getattr(Config, attr))

    def load(self, config_path: Path) -> None:
        with open(config_path, 'r') as ymlfile:
            cfg = yaml.safe_load(ymlfile)
        for attr in _CONFIG_ATTRS:
            if attr in cfg:
                setattr(self, attr, cfg[attr])
        self.upload_folder = str(Path(self.upload_folder).expanduser())

    @classmethod
    def _sync_class(cls) -> None:
        if cls._default_instance is not None:
            for attr in _CONFIG_ATTRS:
                setattr(cls, attr, getattr(cls._default_instance, attr))

    @classmethod
    def load_config(cls, config_path: Path) -> None:
        instance = Config()
        instance.load(config_path)
        cls._default_instance = instance
        cls._sync_class()

    @classmethod
    def config_dir(cls) -> Path:
        # Set up the config path
        if current_system_os() == 'macos':
            local_config_path = Path('~/Library/Application Support/Zordon').expanduser()
        elif current_system_os() == 'windows':
            local_config_path = Path(os.environ['APPDATA']) / 'Zordon'
        else:
            local_config_path = Path('~/.config/Zordon').expanduser()
        return local_config_path

    @classmethod
    def setup_config_dir(cls):
        # Set up the config path
        local_config_dir = cls.config_dir()
        if os.path.exists(local_config_dir):
            return

        try:
            # Create the local configuration directory
            os.makedirs(local_config_dir)

            # Determine the template path
            resource_environment_path = os.environ.get('RESOURCEPATH')
            if resource_environment_path:
                template_path = Path(resource_environment_path) / 'config'
            else:
                template_path = Path(__file__).resolve().parents[2] / 'config'

            # Copy contents from the template to the local configuration directory
            copy_directory_contents(template_path, local_config_dir)

        except Exception as e:
            print(f"An error occurred while setting up the config directory: {e}")
            raise
