"""Normalizes a raw mod folder into the standard cstrike/ directory layout."""

from __future__ import annotations

import shutil
from typing import TYPE_CHECKING

from core.logger_config import logger

if TYPE_CHECKING:
    from pathlib import Path


CSTRIKE_DIRECTORIES = {"addons", "cfg", "sound", "models", "materials", "maps", "resource"}
SOURCEMOD_SUBDIRS = {"plugins", "scripting", "translations", "configs", "gamedata", "extensions"}


def ensure_mod_structure(mod_path: Path, mod_id: str) -> None:
    """Ensures that the mod's directory structure follows the standard /cstrike format."""
    elements = [e for e in mod_path.iterdir() if e.name not in ("manifest.json", "cstrike")]
    cstrike_dir = mod_path / "cstrike"

    if not elements:
        cstrike_dir.mkdir(exist_ok=True)
        return

    logger.info(
        f"[Auto-Init] Non-standard structure detected for the '{mod_id}' mod. Reorganizing..."
    )
    cstrike_dir.mkdir(exist_ok=True)

    for elem in elements:
        target_path = _get_target_path(elem, cstrike_dir)
        _merge_or_move(elem, target_path)


def _get_target_path(elem: Path, cstrike_dir: Path) -> Path:
    """Determines the exact target path of an element according to CSS/SourceMod standards."""
    sm_base = cstrike_dir / "addons" / "sourcemod"

    if elem.is_dir():
        if elem.name in CSTRIKE_DIRECTORIES:
            return cstrike_dir / elem.name
        if elem.name in SOURCEMOD_SUBDIRS:
            return sm_base / elem.name
        if elem.name == "include":
            return sm_base / "scripting" / "include"
        return cstrike_dir / elem.name

    extension_map = {
        ".smx": sm_base / "plugins" / elem.name,
        ".sp": sm_base / "scripting" / elem.name,
        ".cfg": cstrike_dir / "cfg" / elem.name,
        ".txt": sm_base / "configs" / elem.name,
    }
    return extension_map.get(elem.suffix, cstrike_dir / elem.name)


def _merge_or_move(source: Path, target: Path) -> None:
    """Moves a file or neatly merges the contents of an existing folder."""
    target.parent.mkdir(parents=True, exist_ok=True)

    if source.is_dir() and target.exists():
        for sub_item in source.iterdir():
            shutil.move(str(sub_item), str(target / sub_item.name))
        source.rmdir()
    else:
        shutil.move(str(source), str(target))
