import argparse
import json
from utils import add_nexus_arguments, get_nexus_base_url, download_files, validate_manifest_dependencies
from actions_logging.app_logging import logger
from github.env import exit_on_error_and_write_summary, get_required_env_var
import os


def append_error(errors, item, message):
    if item not in errors:
        errors[item] = []
    errors[item].append(message)


def validate_manifest():
    if "name" not in manifest_data:
        exit_on_error_and_write_summary("Missing name")
    if "version" not in manifest_data:
        exit_on_error_and_write_summary("Missing version")
    if "source" not in manifest_data:
        exit_on_error_and_write_summary("Missing source")

    errors = {}

    if "platforms" not in manifest_data:
        exit_on_error_and_write_summary("Missing platforms")

    if not isinstance(manifest_data["platforms"], list):
        exit_on_error_and_write_summary("Invalid platforms: not a list")

    for index, item in enumerate(manifest_data["platforms"]):
        if not isinstance(item, dict):
            append_error(errors, index, "Invalid item: not a dict")
            continue
        if "os" in item and item["os"] not in ["Windows", "Linux", "macOS"]:
            append_error(errors, index, f"Invalid os: {item['os']}")
        if "arch" in item and item["arch"] not in ["ARM64", "X64", "unified"]:
            append_error(errors, index, f"Invalid arch: {item['arch']}")
        if not item["source"]:
            append_error(errors, index, "Missing source")
        if "unzip" in item and not isinstance(item["unzip"], bool):
            append_error(errors, index, "Invalid unzip: not a boolean")
            continue
        if "unzip" in item and item["unzip"] and not item["source"].endswith(".zip"):
            append_error(errors, index, "Invalid unzip: source is not a zip file")
        if "hash" not in item or not item["hash"]:
            append_error(errors, index, "Missing hash")

    if errors:
        logger.error(f"Errors found in {args.manifest_file}:")
        for item in errors:
            logger.error(f"  Item {item}:")
            for message in errors[item]:
                logger.error(f"    {message}")
        exit_on_error_and_write_summary(f"Errors found in {args.manifest_file}")

    if "dependencies" not in manifest_data:
        exit_on_error_and_write_summary("Missing dependencies")

    validate_manifest_dependencies(manifest_data["dependencies"])


if __name__ == "__main__":
    # Parse command-line arguments
    parser = argparse.ArgumentParser(description="Get input parameters")
    add_nexus_arguments(parser)
    parser.add_argument('--download_directory', type=str, help='Destination directory path', required=True)
    parser.add_argument('--manifest_file', type=str, help='Firefly manifest file path', required=True)

    args = parser.parse_args()

    username = get_required_env_var("NEXUS_USERNAME")
    password = get_required_env_var("NEXUS_PASSWORD")

    with open(args.manifest_file, "r") as manifest_file:
        manifest_data = json.load(manifest_file)

    validate_manifest()
    base_url = f"{get_nexus_base_url(args)}/{manifest_data['source']}"

    download_files(username, password, manifest_data["platforms"], base_url, args.download_directory, True)

    dependencies_base_url = get_nexus_base_url(args)

    for dependency in manifest_data["dependencies"]:
        logger.info(f"dependency: {dependency}")
        version = manifest_data["dependencies"][dependency]["version"]
        logger.info(f"version: {version}")
        dependency_url = f"{dependencies_base_url}/{dependency}/{version}"

        download_files(username, password, manifest_data["dependencies"][dependency]["platforms"], dependency_url,
                       args.download_directory, True)

    logger.info_green(f"Files downloaded to {args.download_directory}:")
    for root, dirs, files in os.walk(args.download_directory):
        for file in files:
            logger.info_green(os.path.join(root, file))
