import shutil
import os
import sempy.fabric as fabric
import json
import uuid
from zipfile import ZipFile


class fdtUtils:
    def get_id_by_name(self, name):
        for it in self.deployment_order:
            if it.get("name") == name:
                return it.get("id")
        return None

    def get_schedule_by_name(self, name):
        for it in self.deployment_order:
            if it.get("name") == name:
                return it.get("schedule")
        return None

    def copy_to_tmp(self, name, child=None, type=None):
        child_path = "" if child is None else f".children/{child}/"
        type_path = "" if type is None else f"{type}/"
        shutil.rmtree("./builtin/tmp", ignore_errors=True)
        path2zip = "./builtin/src/src.zip"
        with ZipFile(path2zip) as archive:
            for file in archive.namelist():
                if file.startswith(f"src/{type_path}{name}/{child_path}"):
                    archive.extract(file, "./builtin/tmp")
        return f"./builtin/tmp/src/{type_path}{name}/{child_path}"

    def get_mapping_table_new_from_type(self, type):
        result = ""
        filtered_data = list(
            filter(lambda item: item["Type"] == type, self.mapping_table)
        )
        if len(filtered_data) > 0:
            result = filtered_data[0]["new"]
        return result

    def get_mapping_table_new_from_old(self, old):
        result = ""
        filtered_data = list(
            filter(lambda item: item["old"] == old, self.mapping_table)
        )
        if len(filtered_data) > 0:
            result = filtered_data[0]["new"]
        return result

    def get_mapping_table_new_from_type_item(self, type, item):
        result = ""
        filtered_data = list(
            filter(
                lambda table: table["Type"] == type and table["Item"] == item,
                self.mapping_table,
            )
        )
        if len(filtered_data) > 0:
            result = filtered_data[0]["new"]
        return result

    def get_mapping_table_parent_type(self, type, item, parent_type):
        parent_item = self.get_mapping_table_new_from_type_item(type, item)
        result = self.get_mapping_table_new_from_type_item(parent_type, parent_item)
        return result

    def replace_ids_in_folder(self, folder_path, mapping_table):
        for root, _, files in os.walk(folder_path):
            for file_name in files:
                if file_name.endswith(
                    (".py", ".json", ".pbir", ".platform", ".ipynb", ".py", ".tmdl")
                ) and not file_name.endswith("report.json"):
                    file_path = os.path.join(root, file_name)
                    with open(file_path, "r", encoding="utf-8") as file:
                        content = file.read()
                        for mapping in mapping_table:
                            content = content.replace(mapping["old"], mapping["new"])
                    with open(file_path, "w", encoding="utf-8") as file:
                        file.write(content)

    def fab_update_environments_spark_monitor(
        self, evironments, workspace_name, eventstream_name, connection_name
    ):

        for environment in evironments:
            workspace = environment.get("workspace_id")
            environment = environment.get("environment_id")
            print("################### UPDATING ENVIRONMENT")
            print("workspace: " + workspace)
            print("Environment: " + environment)

            self.trg_workspace_id = self.fab_get_workspace_id(
                f"{workspace_name}.Workspace"
            )
            self.trg_workspace_name = f"{workspace_name}.Workspace"
            eventstream_name = (
                f"{eventstream_name}.Eventstream"
                if ".Eventstream" not in eventstream_name
                else eventstream_name
            )
            connection_string = self.fab_get_eventstream_connection_string(
                eventstream_name, connection_name
            )
            StringSparkProperties = json.dumps(
                {
                    "sparkProperties": {
                        "spark.synapse.diagnostic.emitters": "SparkEmitter",
                        "spark.synapse.diagnostic.emitter.SparkEmitter.type": "AzureEventHub",
                        "spark.synapse.diagnostic.emitter.SparkEmitter.secret": connection_string,
                        "spark.fabric.pools.skipStarterPools": "true",
                    }
                }
            )
            response = self.run_fab_command(
                f"api -X patch /workspaces/{workspace}/environments/{environment}/staging/sparkcompute -i  {StringSparkProperties}",
                capture_output=True,
                silently_continue=True,
            )
            response = self.run_fab_command(
                f"api -X post /workspaces/{workspace}/environments/{environment}/staging/publish ",
                capture_output=True,
                silently_continue=True,
            )
            print("################### FINISH UPDATING ENVIRONMENT")

    def update_capcity_events_eventstream(self, workspace, item_name="CapacityEvents"):
        tmp_path = "./builtin/tmp/export/"

        shutil.rmtree(tmp_path, ignore_errors=True)

        os.makedirs(os.path.dirname(tmp_path), exist_ok=True)

        self.run_fab_command(
            f"export  /{workspace}.Workspace/{item_name}.Eventstream -o {tmp_path} -f ",
            silently_continue=True,
        )

        property_file = f"{tmp_path}{item_name}.Eventstream/eventstream.json"

        new_sources = []
        new_input_nodes = []

        dfCapacities = fabric.list_capacities()
        dfCapacities = dfCapacities.query("Sku != 'PP3'")

        with open(property_file, "r", encoding="utf-8") as file:
            content = json.load(file)
            sources = content.get("sources", [])
            for index, row in dfCapacities.iterrows():
                capacity_id = row["Id"]
                name = row["Display Name"]
                sku = row["Sku"]
                name = f"{name.replace(' ','')}-{sku}"
                name = name.replace("_", "")
                filtered_data = list(
                    filter(
                        lambda table: table.get("properties", {}).get("capacityId")
                        == capacity_id,
                        sources,
                    )
                )
                if len(filtered_data) > 0:
                    new_source = filtered_data.pop()
                    new_input_node = {"name": new_source.get("name")}
                else:
                    new_source = {
                        "id": str(uuid.uuid4()),
                        "name": name,
                        "type": "FabricCapacityUtilizationEvents",
                        "properties": {
                            "eventScope": "Capacity",
                            "capacityId": capacity_id,
                            "includedEventTypes": [
                                "Microsoft.Fabric.Capacity.State",
                                "Microsoft.Fabric.Capacity.Summary",
                            ],
                            "filters": [],
                        },
                    }
                    new_input_node = {"name": name}
                new_sources.append(new_source)
                new_input_nodes.append(new_input_node)
            content["sources"] = new_sources

            for stream in content["streams"]:
                if stream["type"] == "DefaultStream":
                    stream["inputNodes"] = new_input_nodes

        with open(property_file, "w", encoding="utf-8") as file:
            json.dump(content, file, indent=4)

        self.run_fab_command(
            f"import  /{workspace}.Workspace/{item_name}.Eventstream -i {tmp_path}/{item_name}.Eventstream -f ",
            silently_continue=True,
        )
