import os
import subprocess

from dv_launcher.data.constants import Constants
from dv_launcher.services.logging.custom_logger import CustomLogger

logger = CustomLogger()


def list_to_install_addons(constants: Constants, addon_list: list, db_name: str) -> str | None:
    logger.print_status(f"Checking for addons to be installed on database {db_name}")
    try:
        cmd_list_databases = f"docker exec {constants.COMPOSE_PROJECT_NAME}_db psql -U odoo -d {db_name} -t -c \"SELECT name FROM ir_module_module WHERE state='installed';\""
        result = subprocess.run(
            cmd_list_databases,
            shell=True,
            check=True,
            capture_output=True,
            text=True,
        )

        # Create a list of installed addons from the result, filter out empty spaces
        installed_addons = [
            addon.strip()
            for addon in result.stdout.strip().split('\n')
            # Remove empty lines
            if addon.strip()
        ]

        # Get the difference between the addon list and the installed addons
        non_installed_addons = list(set(addon_list) - set(installed_addons))

        # Let the user know which addons will be installed
        if not non_installed_addons:
            logger.print_success(f"No addons to be installed found on database {db_name}")
            return None
        for addon in non_installed_addons:
            logger.print_status(f"Uninstalled addon '{addon}' will be installed on database {db_name}")

        return ','.join(non_installed_addons)
    except subprocess.CalledProcessError as e:
        logger.print_error(f"Error listing installed addons: {str(e)}")
        logger.print_critical(f"Aborting deployment: {e.stderr}")
        exit(1)


def list_addons_in_folder(addons_folder: list[str]) -> list[str]:
    """
    Fetches all addons in the provided addons folder. The function checks if
    the given folder exists and scans for directories representing addons.

    :param addons_folder: The path to the folder containing addon directories.
    :type addons_folder: list[str]
    :return: A list of addon names.
    :rtype: list[str]
    :raises Exception: If the provided addons folder does not exist or is not a directory.
    """

    addons_list = []
    for addon_folder in addons_folder:
        logger.print_status(f"Fetching addons from: {addon_folder}")
        if not os.path.exists(addon_folder):
            logger.print_error(f"Addons folder does not exist: {addon_folder}")
            raise Exception(f"Addons folder does not exist: {addon_folder}")
        elif not os.path.isdir(addon_folder):
            logger.print_error(f"Addons folder is not a directory: {addon_folder}")
            raise Exception(f"Addons folder is not a directory: {addon_folder}")
        else:
            # Filter out hidden directories starting with '.', non-directories and folders without a manifest file
            addons_list.extend(
                item for item in os.listdir(addon_folder)
                if os.path.isdir(os.path.join(addon_folder, item))
                and not item.startswith('.')
                and "__manifest__.py" in os.listdir(os.path.join(addon_folder, item))
            )
            logger.print_success(f"Found {len(addons_list)} addons in folder: {addon_folder}")
    return addons_list


def modify_addons_folders(cwd: str):
    # Read docker-compose.override.yml file and store contents in map
    addon_folders = {}
    if not os.path.exists(f"{cwd}/docker-compose.override.yml"):
        logger.print_warning(f"docker-compose.override.yml file does not exist in {cwd}, new file will be created")

        # Create an empty file and assign 755 permissions
        with open(f"{cwd}/docker-compose.override.yml", "w") as f:
            pass
        os.chmod(f"{cwd}/docker-compose.override.yml", 0o755)


    with open(f"{cwd}/docker-compose.override.yml", "r") as f:
        for line in f:
            if line.strip().startswith("-"):
                line = line.replace("-", "", 1).strip()
                addon_folders.setdefault(line.split(":")[0].strip(), line.split(":")[1].strip())

    if addon_folders:
        for addon in addon_folders:
            logger.print_status(f"Addon: {addon} mapped to folder: {addon_folders[addon]}, do yoy want to keep it?")
            response = ""
            while response not in ["y", "n"]:
                response = input("y/n: ")
                if response not in ["y", "n"]:
                    logger.print_error("Invalid input. Please enter y or n.")
                # logger.print_error(f"Addon: {addon} will be removed from the list")
                # addon_folders.pop(addon)
            if response == "N":
                addon_folders.pop(addon)

    response = ""
    keep_adding = True
    while keep_adding:
        if response == "":
            response = input("Do you want to add more addon folders? y/n:")
        if response not in ["y", "n"]:
            logger.print_error("Invalid input. Please enter y or n.")
        if response == "n":
            keep_adding = False
        if response == "y" and keep_adding:
            addon_folder = input("Enter the path to the addon folder (write \"exit\" to stop):").strip()
            if addon_folder == "exit":
                keep_adding = False
                continue
            if not os.path.exists(addon_folder):
                logger.print_error(f"Addon folder does not exist: {addon_folder}")
                continue
            else:
                addon_folders.setdefault(addon_folder, f"/mnt/extra-addons-{addon_folder.split("/")[-1]}")
                keep_adding = input("Do you want to add more addon folders? y/n:") == "y"

    # Write updated map back to docker-compose.override.yml
    with open(f"{cwd}/docker-compose.override.yml", "w") as f:
        f.write("# This file was auto-generated by dv-launcher \n")
        f.write("services:\n ")
        f.write("  odoo:\n")
        f.write("    volumes:\n")
        for key, value in addon_folders.items():
            f.write(f"      - {key}:{value}\n")

    # Write odoo.conf file
    final_conf = ""
    with open(f"{cwd}/config/odoo.conf", "r") as f:
        for line in f:
            if line.startswith("addons_path"):
                final_conf += f"addons_path = /usr/lib/python3/dist-packages/odoo/addons,{','.join(addon_folders.values())}\n"
            else:
                final_conf += line

    print(final_conf)

    with open(f"{cwd}/config/odoo.conf", "w") as f:
        f.write(final_conf)

    print(addon_folders)
