import os
import re
from typing import List

from .consts import (
    FOLDERS_NETWORK_LEVEL,
    FOLDERS_NETWORK_AND_HOSTS_LEVELS,
    FILES_NETWORK_LEVEL,
    FILES_NETWORK_AND_HOST_LEVELS,
    FILE_NOTES,
    FOLDER_HOSTS,
    FILE_USERS,
)


from .utils import logger

from .consolidate_functions import consolidate_all


def init_mission(mission_path: str, *, hosts: List[str] = None):
    """Init folder structure for a new mission"""

    # Check if pat halready exists
    if os.path.exists(mission_path):
        raise FileExistsError(f"Path {mission_path} already exists")

    absolute_mission_path = os.path.abspath(mission_path)
    folders = [*FOLDERS_NETWORK_LEVEL, *FOLDERS_NETWORK_AND_HOSTS_LEVELS]
    files = [*FILES_NETWORK_LEVEL, *FILES_NETWORK_AND_HOST_LEVELS]
    _init_mission_or_host(mission_path, folders=folders, files=files)

    # Create notes.txt
    notes_path = os.path.join(mission_path, FILE_NOTES)
    with open(notes_path, "w") as f:
        logger.info(f"Init {FILE_NOTES}")
        f.write(
            f"""# Init
```bash
bash
mission_path={absolute_mission_path}
target=<MODIFY ME>
rate=500
cd $mission_path
```

# Hosts

"""
        )

    # For each host init host
    if hosts:
        for host in hosts:
            init_host(mission_path, host)

    # Consolidate everything
    consolidate_all(mission_path, fast=False)


def _init_mission_or_host(root_path: str, *, folders: List[str], files: List[str]):
    """Factored function to be used when initiating mission or host structure folders"""
    os.makedirs(root_path)

    # Create all folders
    for folder_path in folders:
        logger.info(f"Creating folder {folder_path}")
        path = os.path.join(root_path, folder_path)
        os.makedirs(path)

    for file_path in files:
        logger.info(f"Creating file {file_path}")
        path = os.path.join(root_path, file_path)
        with open(path, "w"):
            pass

    # Add default users
    users_path = os.path.join(root_path, FILE_USERS)
    with open(users_path, "a") as f:
        users = ["root", "administrator"]
        for user in users:
            logger.info(f"Adding {user!r}' to {FILE_USERS}")
            f.write(f"{user}\n")


def init_host(mission_path: str, name: str):
    """Init host structure inside mission path structure"""
    if not os.path.exists(mission_path):
        raise ValueError(f"Mission path {mission_path} doesn't exists")

    host_path = os.path.join(mission_path, FOLDER_HOSTS, name)

    _init_mission_or_host(
        host_path,
        folders=FOLDERS_NETWORK_AND_HOSTS_LEVELS,
        files=FILES_NETWORK_AND_HOST_LEVELS,
    )

    notes_path = os.path.join(mission_path, FILE_NOTES)
    with open(notes_path) as f:
        notes = f.read()

    # Add section for host in notes.md
    if not re.match(rf"^## {name}", notes):
        with open(notes_path, "a") as f:
            f.write(f"\n## {name}\n\n")
            f.write("### Notes\n\n")

            f.write("### Ports\n\n- [ ] 21 FTP ...\n\n")

            f.write("### Privesc\n\n")

            f.write("### Commands\n\n")
            f.write("```bash\n```\n\n")
