# config_manager.py
import configparser
import os
import sys

CONFIG_FILE = "config.ini"

DEFAULT_CONFIG = {
    "Timeouts": {
        "download_wait_timeout": "360",
        "failure_wait_seconds": "5",
        "download_stability_interval": "3",  # Float allowed
        "download_stability_checks": "5",
        # Added more specific timeouts for direct downloads
        "direct_download_timeout": "30",  # Connection timeout
        "direct_idle_timeout": "60",  # Timeout between receiving chunks
        "direct_total_timeout": "1800",  # Overall timeout for a single direct download (30 mins)
        # Added specific waits used within downloader/handlers
        "direct_wait_timeout": "60.0",  # Generic wait in downloader (float)
        "selenium_wait_timeout": "10.0",  # Generic wait in downloader (float)
    },
    "Selenium": {
        "headless": "false",
        "page_load_timeout": "90",
        "navigation_wait": "3",  # Float allowed
        "pixeldrain_button_wait": "45",  # Float allowed
        "mega_button_wait": "60",  # Float allowed
        "mediafire_button_wait": "15",  # Float allowed
    },
    "Misc": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
        "item_processing_delay": "0.1",  # Float allowed
        "debug_mode": "false",  # Added for verbose console logging
        "log_level": "INFO",  # Added: DEBUG, INFO, WARNING, ERROR, CRITICAL
    },
    # Added Parallel section
    "Parallel": {
        "max_direct_downloads": "5",
        "max_selenium_workers": "2",
    },
}


def load_config():
    """Loads configuration from config.ini, falling back to defaults."""
    config = configparser.ConfigParser(interpolation=None)  # Disable interpolation

    # --- Read Defaults First ---
    # Use read_dict to load defaults without marking them as "read from file"
    config.read_dict(DEFAULT_CONFIG)

    # --- Read User Config File (if exists) ---
    if os.path.exists(CONFIG_FILE):
        try:
            # Use read() which merges with existing defaults
            files_read = config.read(CONFIG_FILE, encoding="utf-8")
            if files_read:
                print(f"Configuration loaded successfully from {CONFIG_FILE}.")
            else:
                print(
                    f"Warning: Could not read '{CONFIG_FILE}'. File might be empty or invalid. Using defaults.",
                    file=sys.stderr,
                )
        except configparser.Error as e:
            print(
                f"Warning: Error reading config file {CONFIG_FILE}: {e}. Using default configuration for missing/invalid values.",
                file=sys.stderr,
            )
    else:
        print(
            f"Configuration file {CONFIG_FILE} not found. Using default configuration."
        )
        # Optionally, write the default config to a new file
        try:
            # Create a temporary parser JUST for writing defaults
            default_writer = configparser.ConfigParser(interpolation=None)
            default_writer.read_dict(DEFAULT_CONFIG)
            with open(CONFIG_FILE, "w", encoding="utf-8") as configfile:
                default_writer.write(configfile)
            print(f"Created default configuration file: {CONFIG_FILE}")
        except IOError as e:
            print(
                f"Warning: Could not write default config file {CONFIG_FILE}: {e}",
                file=sys.stderr,
            )

    # --- Ensure Required Sections/Options Exist (using defaults if needed) ---
    # This loop ensures that if the user file is missing sections/options,
    # the defaults loaded earlier are still present in the final config object.
    needs_update = False
    for section, options in DEFAULT_CONFIG.items():
        if not config.has_section(section):
            # This case should be rare now since we load defaults first, but good practice
            print(
                f"Warning: Section '[{section}]' was missing. Added default section.",
                file=sys.stderr,
            )
            config.add_section(section)
            needs_update = True  # Mark that the file might need updating if it exists
        for key, default_value in options.items():
            if not config.has_option(section, key):
                print(
                    f"Warning: Option '{key}' missing in '[{section}]'. Using default: {default_value}",
                    file=sys.stderr,
                )
                config.set(
                    section, key, default_value
                )  # Ensure default is set in the object
                needs_update = True

    # Optionally rewrite the user's config file if defaults were added and the file exists
    # This helps users see all available options. Be cautious if users might not want this.
    # if needs_update and os.path.exists(CONFIG_FILE):
    #     try:
    #         print(f"Updating '{CONFIG_FILE}' with missing default values...")
    #         with open(CONFIG_FILE, 'w', encoding='utf-8') as configfile:
    #             config.write(configfile)
    #     except IOError as e:
    #         print(f"Warning: Could not update config file with defaults: {e}", file=sys.stderr)

    # --- Type Conversions (Example - better to do this where value is used) ---
    # It's generally safer to get the type when needed using getint/getfloat/getboolean
    # Example: timeout = config.getint('Timeouts', 'download_wait_timeout', fallback=360)

    return config


# Example Usage (for testing)
if __name__ == "__main__":
    print("Loading configuration...")
    config = load_config()

    print("\nLoaded Configuration:")
    for section in config.sections():
        print(f"[{section}]")
        for key, value in config.items(section):
            print(f"  {key} = {value}")

    print("\nExample of retrieving converted values:")
    try:
        timeout = config.getint("Timeouts", "download_wait_timeout")
        print(f"  download_wait_timeout (as int): {timeout}")
        direct_timeout = config.getfloat("Timeouts", "direct_download_timeout")
        print(f"  direct_download_timeout (as float): {direct_timeout}")
        headless = config.getboolean("Selenium", "headless")
        print(f"  headless (as boolean): {headless}")
        delay = config.getfloat("Misc", "item_processing_delay")
        print(f"  item_processing_delay (as float): {delay}")
        debug = config.getboolean("Misc", "debug_mode")
        print(f"  debug_mode (as boolean): {debug}")
        log_level = config.get("Misc", "log_level")
        print(f"  log_level (as string): {log_level}")
        # Attempting to get output_dir will now raise an error if not in config.ini
        # output_dir = config.get("Misc", "output_dir")
        # print(f"  output_dir (as string): {output_dir}")
        max_direct = config.getint("Parallel", "max_direct_downloads")
        print(f"  max_direct_downloads (as int): {max_direct}")
        max_selenium = config.getint("Parallel", "max_selenium_workers")
        print(f"  max_selenium_workers (as int): {max_selenium}")

    except (configparser.NoSectionError, configparser.NoOptionError, ValueError) as e:
        print(f"\nError retrieving specific config value: {e}")
