import json
import os
import shutil
import zipfile
from dataclasses import dataclass
from enum import Enum

import GN.Logger as Log
from GN.ContentLibrary.Core import AssetTypes

logger = Log.get_logger(__name__)

# We only consider working with these formats
SUPPORTED_3D_FORMATS = "fbx", "gltf"
SUPPORTED_2D_FORMATS = "png", "jpg", "jpeg"


class AllowedFabTypes(Enum):
    MODELS_3D = "3D Models"
    MODELS_3D2 = "3D"
    MATERIAL_TEXTURES = "Material & Textures"
    DECALS = "Decals"
    ATLASES = "Atlases"

    @classmethod
    def is_allowed(cls, asset_type_str: str):
        return asset_type_str in cls._value2member_map_


FAB_TYPE_TO_DASH_TYPE = {
    AllowedFabTypes.MODELS_3D: AssetTypes.ASSET_3D,
    AllowedFabTypes.MODELS_3D2: AssetTypes.ASSET_3D,
    AllowedFabTypes.MATERIAL_TEXTURES: AssetTypes.ASSET_PF_SURFACES_FPS,
    AllowedFabTypes.DECALS: AssetTypes.ASSET_DECALS,
    AllowedFabTypes.ATLASES: AssetTypes.ASSET_ATLAS_2D
}

@dataclass
class FabData:
    identifier: str
    asset_name = ""
    vendor = ""
    asset_type = ""
    image = None
    tags = []
    hierarchy = []

    @staticmethod
    def from_dict(fab_dict: dict):
        out = FabData(identifier=fab_dict.get("identifier"))

        out.asset_name = fab_dict.get("asset_name")
        out.vendor = fab_dict.get("vendor")
        out.asset_type = fab_dict.get("asset_type")
        out.image = fab_dict.get("image")
        out.tags = fab_dict.get("tags")
        out.hierarchy = fab_dict.get("hierarchy")
        return out

    def __repr__(self):
        return (f"FabData(identifier={self.identifier}, "
                f"asset_name={self.asset_name}, "
                f"vendor={self.vendor}, "
                f"asset_type={self.asset_type}, "
                f"image={self.image}, "
                f"tags={self.tags}, "
                f"hierarchy={self.hierarchy})")



def get_data_to_copy(cache_path):
    """From a source folder with fab downloads, get the relevant archives to copy to the destination cache"""
    return [f for f in os.listdir(cache_path) if f.endswith(".zip")]


def copy_data(source_cache_path, dest_cache_path) -> list[str]:
    """Copy data from the source cache to the destination cache, ensuring only zip files are copied"""
    source_folders = get_data_to_copy(source_cache_path)
    dest_folders = get_data_to_copy(dest_cache_path)

    new_folders = [f for f in source_folders if f not in dest_folders]
    logger.debug(f"New archives: {new_folders}")

    copied = list()

    if new_folders:
        logger.debug(f"Copying {len(new_folders)} new folders")
        for curr_folder in new_folders:
            cuss_source_path = os.path.join(source_cache_path, curr_folder)
            curr_dest_path = os.path.join(dest_cache_path, curr_folder)

            # Ensure the zip file is valid
            if zipfile.is_zipfile(cuss_source_path):
                shutil.copy(cuss_source_path, curr_dest_path)
                logger.debug(f"Copied {cuss_source_path} to {curr_dest_path}")
                copied.append(curr_dest_path)
            else:
                logger.debug(f"Invalid zip file: {cuss_source_path}")

    return copied


def check_archive_contains_supported_files(zip_archive: zipfile.ZipFile):
    found_fbx = False
    found_gltf = False
    found_images = False

    for file_info in zip_archive.infolist():
        f_extension = file_info.filename.split(".")[-1]
        if f_extension == SUPPORTED_3D_FORMATS[0]:
            found_fbx = True
        elif f_extension == SUPPORTED_3D_FORMATS[1]:
            found_gltf = True
        elif f_extension in SUPPORTED_2D_FORMATS:
            found_images = True

    return found_fbx, found_gltf, found_images


def data_to_cache(fab_data: FabData, dest_cache_path: str):
    """Saves some fab data to a metadata file ready to be read from the Dash library"""
    metadata_file = os.path.join(dest_cache_path, "metadata.json")

    # Create a folder in the destination cache
    os.makedirs(dest_cache_path, exist_ok=True)

    # Build basic data needed for the library
    metadata = {
        "name": fab_data.asset_name,
        "description": "Fab asset",
        "identifier": fab_data.identifier,
        "asset_type": fab_data.asset_type,
        "thumbnail": os.path.basename(fab_data.image),
        "tags": fab_data.tags,
        "hierarchy": fab_data.hierarchy,
        "categories": [""],
        "tiers": list(range(len(get_data_to_copy(dest_cache_path)))),

        "vendor": fab_data.vendor,
    }

    with open(metadata_file, "w") as f:
        json.dump(metadata, f, indent=4)


if __name__ == "__main__":
    print(AllowedFabTypes.is_allowed("3D Models"))
