import json
import shutil

import docker
import os

from docker.errors import NotFound

from .port_utils import assign_ports

client = docker.from_env()

DEFAULT_CONFIG = {
    "max-players": 20,
    "pvp": True,
    "difficulty": "easy",
    "online-mode": True,
    "spawn-monsters": True,
    "spawn-animals": True,
    "allow-nether": True,
    "max-build-height": 256,
    "view-distance": 10
}


def get_server_config(username):
    server_info_path = f"./servers/mc-{username}/server_info.json"

    if not os.path.exists(server_info_path):
        server_info = {
            "type": "paper",
            "version": "latest",
            "config": DEFAULT_CONFIG.copy()
        }
        os.makedirs(os.path.dirname(server_info_path), exist_ok=True)
        with open(server_info_path, "w") as f:
            json.dump(server_info, f, indent=4)
        return DEFAULT_CONFIG.copy(), "paper", "latest"

    with open(server_info_path, "r") as f:
        server_info = json.load(f)

    server_type = server_info.get("type", "paper")
    server_version = server_info.get("version", "latest")
    server_config = server_info.get("config", DEFAULT_CONFIG.copy())

    updated = False

    for key, default_value in DEFAULT_CONFIG.items():
        if key not in server_config:
            server_config[key] = default_value
            updated = True

    if updated:
        server_info["config"] = server_config
        with open(server_info_path, "w") as f:
            json.dump(server_info, f, indent=4)
    return server_config, server_type, server_version


def save_server_info(username, server_type, server_version):
    server_info_path = f"./servers/mc-{username}/server_info.json"
    server_info = {
        "type": server_type,
        "version": server_version,
        "config": DEFAULT_CONFIG.copy()
    }
    os.makedirs(os.path.dirname(server_info_path), exist_ok=True)
    with open(server_info_path, "w") as f:
        json.dump(server_info, f)
    assign_ports(username)


def get_server_info(username):
    server_info_path = f"./servers/mc-{username}/server_info.json"
    if os.path.exists(server_info_path):
        with open(server_info_path, "r") as f:
            return json.load(f)
    return None


def start_server(username):
    name = f"mc-{username}"
    ports = assign_ports(username)
    path = f"./servers/{name}"
    os.makedirs(path, exist_ok=True)
    server_config, server_type, server_version = get_server_config(username)

    environment = {
        "EULA": "TRUE",
        "SERVER_PORT": ports[0],
        "ENABLE_RCON": "TRUE",
        "USE_AIKAR_FLAGS": "TRUE",
        "MOTD": f"Serwer użytkownika §9{username}",
        "TYPE": server_type,
        "VERSION": server_version,
        "MAX_PLAYERS": server_config["max-players"],
        "PVP": "TRUE" if server_config["pvp"] else "FALSE",
        "DIFFICULTY": server_config["difficulty"],
        "SPAWN_MONSTERS": "TRUE" if server_config["spawn-monsters"] else "FALSE",
        "SPAWN_ANIMALS": "TRUE" if server_config["spawn-animals"] else "FALSE",
        "ALLOW_NETHER": "TRUE" if server_config["allow-nether"] else "FALSE",
        "MAX_BUILD_HEIGHT": server_config["max-build-height"],
        "VIEW_DISTANCE": server_config["view-distance"],
        "ONLINE_MODE": "TRUE" if server_config["online-mode"] else "FALSE",
        "INIT_MEMORY": "1G",
        "MAX_MEMORY": "4G"
    }

    if server_config["andus-drasl"]:
        drasl_args = (
            "-Dminecraft.api.env=custom "
            "-Dminecraft.api.auth.host=https://drasl.andus.ovh/auth "
            "-Dminecraft.api.account.host=https://drasl.andus.ovh/account "
            "-Dminecraft.api.session.host=https://drasl.andus.ovh/session "
            "-Dminecraft.api.services.host=https://drasl.andus.ovh/services"
        )
        environment["JVM_OPTS"] = drasl_args
        print(f"server {username} uses drasl {drasl_args}")
        print(f"env: {environment}")

    client.containers.run(
        "itzg/minecraft-server",
        detach=True,
        name=f"mc-{username}",
        ports={
            f"{ports[0]}/tcp": ports[0],
            f"{ports[1]}/tcp": ports[1],
            f"{ports[2]}/tcp": ports[2],
        },
        volumes=[
            f"{os.path.abspath(path)}:/data"
        ],
        environment=environment,
        restart_policy={"Name": "unless-stopped"}
    )


def stop_server(username):
    name = f"mc-{username}"
    container = client.containers.get(name)
    container.stop()
    container.remove()


def restart_server(username):
    name = f"mc-{username}"
    container = client.containers.get(name)
    container.stop()
    container.remove()
    start_server(username)


def delete_server(username):
    container_name = f"mc-{username}"
    server_path = f"./servers/{container_name}"

    try:
        container = client.containers.get(container_name)
        container.stop()
        container.remove()
    except NotFound:
        pass

    if os.path.exists(server_path):
        shutil.rmtree(server_path)

    from .port_utils import free_ports_for_user
    free_ports_for_user(username)

    return f"Serwer {container_name} został usunięty."


def get_logs(username):
    name = f"mc-{username}"
    container = client.containers.get(name)
    return container.logs(tail=100).decode()
