# Copyright (C) 2025 James Brotosky, Brandon Wickline
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import logging
import logging.config
import logging.handlers
import os
from pathlib import Path
import platform

from dotenv import load_dotenv, set_key

from utils.configmanager import (
    get_system_value,
    load_system_config,
    load_user_config,
)


def get_base_directory() -> Path:
    system = platform.system()
    home = Path.home()
    if system == "Windows":
        return Path(os.getenv("APPDATA", home / "AppData" / "Roaming")) / "Loxide"
    elif system == "Darwin":
        return home / "Library" / "Application Support" / "Loxide"
    else:
        return home / ".local" / "share" / "Loxide"


def configure_logging(log_dir: Path, log_level: str = "INFO"):
    log_file = log_dir / "Loxide.log"

    config = {
        "version": 1,  # Required key for dictConfig format version
        "disable_existing_loggers": False,  # Keeps existing loggers active
        "formatters": {
            "detailed": {
                "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
                # Includes timestamp, logger name, level, and message
            },
            "simple": {
                "format": "%(levelname)s - %(message)s"
                # Minimal format for console output
            },
        },
        "handlers": {
            "file": {
                "class": "logging.handlers.TimedRotatingFileHandler",
                "filename": str(log_file),
                "when": "midnight",  # Rotate logs at midnight
                "interval": 1,  # Every 1 day
                "backupCount": 7,  # Keep 7 days of logs
                "encoding": "utf-8",  # Ensure UTF-8 encoding
                "level": "DEBUG",  # Always log DEBUG and above to file
                "formatter": "detailed",  # Use detailed format
            },
            "console": {
                "class": "logging.StreamHandler",
                "level": log_level.upper(),  # System-configured level for console
                "formatter": "simple",  # Use simple format
            },
        },
        "root": {
            "level": "DEBUG",  # Root logger level
            "handlers": ["file", "console"],  # Attach both handlers
        },
    }

    # Add Windows Event Log handler if on Windows
    if platform.system() == "Windows":
        try:
            config["handlers"]["eventlog"] = {
                "class": "logging.handlers.NTEventLogHandler",
                "appname": "Loxide",  # Event log source name
                "level": "CRITICAL",  # Only log critical errors
                "formatter": "simple",  # Use simple format
            }
            config["root"]["handlers"].append("eventlog")
        except Exception as e:
            logging.warning(f"Could not attach Windows Event Log handler: {e}")

    # Apply the logging configuration
    logging.config.dictConfig(config)
    logging.getLogger().debug("✅ Logging configured.")


def setup():
    """
    Initialize the application environment:
    1. Create directory structure
    2. Load system config (immutable, from system_config.json)
    3. Load user config (mutable, from user_config.json)
    4. Configure logging
    5. Set up .env with WORKING_DIR only
    """
    base_dir = get_base_directory()
    dirs = {
        "config": base_dir / "config",
        "cache": base_dir / "cache",
        "logs": base_dir / "logs",
    }

    for name, path in dirs.items():
        path.mkdir(parents=True, exist_ok=True)
        logging.debug(f"{name.capitalize()} directory ensured at: {path}")

    # Load system config (immutable)
    system_config = load_system_config()

    # Configure logging with system-defined log level
    log_level = get_system_value("LOG_LEVEL", str, "INFO")
    configure_logging(dirs["logs"], log_level)

    # Load user config (mutable)
    user_config = load_user_config(dirs["config"])

    # Set up .env file - ONLY for WORKING_DIR (runtime-configurable value)
    env_path = base_dir / ".env"
    if not env_path.exists():
        env_path.touch()
    load_dotenv(dotenv_path=env_path, override=True)

    # Set up working directory (only dynamic value in .env)
    working_dir = Path(os.getenv("WORKING_DIR") or (base_dir / "data"))
    working_dir.mkdir(parents=True, exist_ok=True)
    set_key(str(env_path), "WORKING_DIR", str(working_dir))
    os.environ["WORKING_DIR"] = str(working_dir)
    logging.debug(f"Working directory set to: {working_dir}")

    # Create folder structure in working directory
    folders_structure = {
        "Approved": [],
        "Needs_Review": ["Review_First", "Review_Second", "HTML"],
        "Preflight": ["HTML"],
        "Archived": [],
    }

    for folder_name, subfolders in folders_structure.items():
        folder_path = working_dir / folder_name
        folder_path.mkdir(parents=True, exist_ok=True)
        logging.debug(f"'{folder_name}' folder ensured at: {folder_path}")
        for subfolder in subfolders:
            subfolder_path = folder_path / subfolder
            subfolder_path.mkdir(parents=True, exist_ok=True)
            logging.debug(f" └─ '{subfolder}' subfolder created at: {subfolder_path}")

    logging.info("✅ Setup complete")
