import io
import json
import logging
import os

import py7zr

logger = logging.getLogger("waa_cube.vm_backend.getters.fileexplorer")


def get_vm_folder_exists_in_documents(env, config) -> bool:
    documents_path = env.controller.get_vm_documents_path()
    logger.info(f"Documents path: {documents_path}")
    folder_name = config["folder_name"]
    logger.info(f"Folder name: {folder_name}")
    if env.controller.get_vm_folder_exists_in_path(folder_name, documents_path):
        logger.info(f"Folder {folder_name} exists in documents")
        return True
    else:
        logger.info(f"Folder {folder_name} does not exist in documents")
        return False


def get_vm_file_exists_in_desktop(env, config) -> bool:
    desktop_path = env.controller.get_vm_desktop_path()
    logger.info(f"Desktop path: {desktop_path}")
    file_name = config["file_name"]
    logger.info(f"File name: {file_name}")
    if env.controller.get_vm_file_exists_in_path(file_name, desktop_path):
        logger.info(f"File {file_name} exists in desktop")
        return True
    else:
        logger.info(f"File {file_name} does not exist in desktop")
        return False


def get_vm_file_exists_in_vm_folder(env, config) -> bool:
    """Generalisation of ``get_vm_file_exists_in_desktop`` to any folder.

    Config keys: ``folder_name`` (full VM path), ``file_name`` (basename).
    """
    folder_path = config["folder_name"]
    file_name = config["file_name"]
    logger.info(f"Checking for {file_name} in {folder_path}")
    if env.controller.get_vm_file_exists_in_path(file_name, folder_path):
        logger.info(f"File {file_name} exists in {folder_path}")
        return True
    logger.info(f"File {file_name} does not exist in {folder_path}")
    return False


def get_are_files_sorted_by_modified_time(env, config: dict) -> bool:
    if not config["directory"]:
        return False
    return env.controller.get_vm_are_files_sorted_by_modified_time(config["directory"])


def get_is_file_saved_desktop(env, config) -> str:
    desktop_path = env.controller.get_vm_desktop_path()
    file_name = config["filename"]
    file = env.controller.get_file_as_text(desktop_path + "\\" + file_name)
    if file is not None and config["textcontent"] in file:
        return "true"
    else:
        return "false"


def get_is_details_view(env, config):
    if not config["folder_path"]:
        return False
    is_details_view = env.controller.get_vm_file_explorer_is_details_view(config["folder_path"])
    return is_details_view


def get_all_png_file_names(env, config):
    file_path = config["file_path"]
    folder_path = config["folder_path"]
    # Python script that:
    # - Reads the content of the text file generated by Agent
    # - Gets all .png files in the folder
    script = f"""
import os
from sys import exit
def read_file(file_path):
    with open(file_path, 'r') as f:
        return set(f.read().splitlines())
def get_png_files(folder_path):
    return set([f for f in os.listdir(folder_path) if f.lower().endswith('.png')])

if not os.path.exists('{file_path}'):
    print("File {file_path} does not exist")
    exit()

file_content = read_file(r'{file_path}')
png_files = get_png_files(r'{folder_path}')
print("File content:", repr(list(file_content)))
print("PNG files:", repr(list(png_files)))
print("Result:", "true" if file_content == png_files else "false")
"""
    response = env.controller.execute_python_command(script)
    logger.info(f"Script response: {response}")

    if response["status"] != "success":
        logger.error(f"Failed to execute script: {response}")
        return "false"
    # Parse the output
    output_lines = response["output"].strip().split("\n")
    if output_lines[0] == f"File {file_path} does not exist":
        logger.error("Text file does not exist")
        return "false"
    file_content = eval(output_lines[0].split(":", 1)[1])
    png_files = eval(output_lines[1].split(":", 1)[1])
    result = output_lines[2].split(":", 1)[1].strip()
    logger.info(f"PNG file names check result: {result}")
    logger.info(f"Files in text file: {set(file_content)}")
    logger.info(f"Actual PNG files: {set(png_files)}")
    return result


def get_zipped_folder_in_desktop(env, config) -> str:
    folder_name = config["filename"]
    zippedFile = env.controller.get_file(folder_name)
    file = io.BytesIO(zippedFile)
    with py7zr.SevenZipFile(file, mode="r", password=config["password"]) as z:
        if not z.needs_password():
            return "false"
        # py7zr's old `readall()` returned a dict of {path: data}; current API
        # is getnames() for filename-only checks (and read([targets]) for content).
        for name in z.getnames():
            if name == "OldProjects/example.txt":
                return "true"
    return "false"


def get_is_all_docx_in_archive(env, config) -> str:
    folder_path = config["folder_path"]
    if not folder_path:
        logger.info("folder_path not provided in config")
        return "false"
    # Check if the folder exists
    folder_exists = env.controller.execute_python_command(f"import os; print(os.path.exists('{folder_path}'))")
    if folder_exists["output"].strip().lower() != "true":
        logger.info(f"Folder {folder_path} does not exist")
        return "false"
    # 1. Check if "Archive" folder exists
    archive_path = os.path.join(folder_path, "Archive")
    archive_exists = env.controller.execute_python_command(f"import os; print(os.path.exists('{archive_path}'))")
    if archive_exists["output"].strip().lower() != "true":
        logger.info("Archive folder does not exist")
        return "false"
    # 2. Check if all files in Archive folder are .docx files
    list_archive_files = env.controller.execute_python_command(
        f"import os; print(','.join([f for f in os.listdir('{archive_path}') if os.path.isfile(os.path.join('{archive_path}', f))]))"
    )
    archive_files = list_archive_files["output"].strip().split(",")
    if not all(file.lower().endswith(".docx") for file in archive_files):
        logger.info("Not all files in Archive folder are .docx files")
        return "false"
    # 3. Check if no .docx files exist directly under folder_path
    list_folder_files = env.controller.execute_python_command(
        f"import os; print(','.join([f for f in os.listdir('{folder_path}') if os.path.isfile(os.path.join('{folder_path}', f))]))"
    )
    folder_files = list_folder_files["output"].strip().split(",")
    if any(file.lower().endswith(".docx") for file in folder_files):
        logger.info("Found .docx files directly under folder_path")
        return "false"
    # All conditions met
    return "true"


def get_is_file_hidden(env, config):
    if not config or "file_path" not in config:
        logger.error("file_path is invalid")
        return "false"
    result = env.controller.get_file_hidden_status(config["file_path"])
    if result == 1:
        return "true"
    else:
        return "false"


def get_vm_active_window_title(env, config) -> str:
    window_title = env.controller.execute_python_command("import pyautogui; print(pyautogui.getActiveWindowTitle())")[
        "output"
    ].strip()
    logger.info(f"Window title: {window_title}")
    return window_title


def get_is_directory_read_only_for_user(env, config) -> bool:
    if not config["directory"]:
        raise ValueError("directory is required")
    if not config["user"]:
        raise ValueError("user is required")
    return env.controller.get_vm_is_directory_read_only_for_user(config["directory"], config["user"])


def get_are_all_images_tagged(env, config) -> bool:
    if not config["directory"]:
        raise ValueError("directory is required")
    if not config["tag"]:
        raise ValueError("tag is required")
    return env.controller.get_vm_are_all_images_tagged(config["directory"], config["tag"])


def get_is_file_desktop(env, config) -> str:
    desktop_path = env.controller.get_vm_desktop_path()
    file_name = config["filename"]
    file = env.controller.get_file(desktop_path + "\\" + file_name)
    if file is not None:
        return "true"
    return "false"


def get_is_files_moved_downloads(env, config) -> str:
    file_name = config["file_name"]
    folder_name = config["folder_name"]

    downloads_directory = json.dumps(env.controller.get_vm_directory_tree("C:\\Users\\Docker\\Downloads"))
    old_downloads_directory = env.controller.get_vm_directory_tree("C:\\Users\\Docker\\OldDownloads")

    if file_name in downloads_directory and folder_name in downloads_directory:
        return "false"

    for key in old_downloads_directory:
        if type(old_downloads_directory[key]) is list:
            for i in old_downloads_directory[key]:
                if i["type"] == "directory":
                    if i["name"] == folder_name:
                        for j in i["children"]:
                            if j["name"] == file_name:
                                return "true"

    return "false"


def get_vm_library_folders(env, config) -> list:
    if "library_name" not in config:
        raise ValueError("library_name is required")
    library_name = config["library_name"]
    logger.info(f"Library name: {library_name}")
    return env.controller.get_vm_library_folders(library_name)
