"""Fabric deployment tool template package."""

from __future__ import annotations

from importlib.metadata import version

import os
import json
from ._fab_cli import fdtCLU
from ._git import fdtGit
from ._util import fdtUtils
from ._fab_item_management import fdtItemManagement
import notebookutils

__all__ = [
    "__version__",
    "FabDeploymentTool",
]

try:
    __version__ = version("fabric-deployment-tool")
except Exception:  # pragma: no cover
    __version__ = "0.0.0"


class FabDeploymentTool(fdtCLU, fdtGit, fdtUtils, fdtItemManagement):
    src_workspace_id = ""
    src_workspace_name = ""
    trg_workspace_id = ""
    trg_workspace_name = ""
    deployment_order = []
    mapping_table = []
    workspace_name = ""
    capacity_name = ""
    eventhouse_name = ""
    repo_owner = ""
    repo_name = ""
    branch = ""
    folder_prefix = ""
    github_token = ""
    pipeline_parameters = {}

    def __init__(self):
        # Set environment parameters for Fabric CLI
        token = notebookutils.credentials.getToken("pbi")
        os.environ["FAB_TOKEN"] = token
        os.environ["FAB_TOKEN_ONELAKE"] = token

    def run(
        self,
        workspace_name,
        capacity_name="",
        eventhouse_name="",
        exclude=[],
        type_exclude=[],
        pipeline_parameters={},
    ):
        self.download_folder_as_zip(
            self.repo_owner,
            self.repo_name,
            output_zip="./builtin/src/src.zip",
            branch=self.branch,
            folder_to_extract=f"{self.folder_prefix}/src",
            folder_prefix=f"{self.folder_prefix}",
            github_token=self.github_token,
        )
        self.download_folder_as_zip(
            self.repo_owner,
            self.repo_name,
            output_zip="./builtin/config/config.zip",
            branch=self.branch,
            folder_to_extract=f"{self.folder_prefix}/config",
            folder_prefix=f"{self.folder_prefix}",
            github_token=self.github_token,
        )
        self.uncompress_zip_to_folder(
            zip_path="./builtin/config/config.zip", extract_to="./builtin"
        )
        base_path = "./builtin/"

        self.eventhouse_name = eventhouse_name
        self.pipeline_parameters = pipeline_parameters
        deploy_order_path = os.path.join(base_path, "config/deployment_order.json")
        with open(deploy_order_path, "r") as file:
            self.deployment_order = json.load(file)

        # deploy workspace idempotent
        if "NotFound" in self.fab_workspace_exists(f"{workspace_name}.Workspace"):
            if capacity_name == "" or capacity_name is None:
                raise "Workspace doesn´t exist and capacity_name not provided"
            self.run_fab_command(
                f"mkdir {workspace_name}.Workspace -P capacityname={capacity_name}.Capacity"
            )
            print(f"New Workspace Create", flush=True)

        self.src_workspace_name = "Workspace.src"
        self.src_workspace_id = self.get_id_by_name(self.src_workspace_name)
        self.trg_workspace_id = self.fab_get_workspace_id(f"{workspace_name}.Workspace")
        self.trg_workspace_name = f"{workspace_name}.Workspace"

        print(f"Target Workspace Id: {self.trg_workspace_id}", flush=True)
        print(f"Target Workspace Name: {self.trg_workspace_name}", flush=True)

        self.mapping_table.append(
            {
                "Type": "Workspace Id",
                "Item": self.trg_workspace_name,
                "old": self.get_id_by_name(self.src_workspace_name),
                "new": self.trg_workspace_id,
            }
        )
        self.mapping_table.append(
            {
                "Type": "Workspace Blank Id",
                "Item": self.trg_workspace_name,
                "old": "00000000-0000-0000-0000-000000000000",
                "new": self.trg_workspace_id,
            }
        )
        self.mapping_table.append(
            {
                "Type": "Workspace Name",
                "Item": self.trg_workspace_name,
                "old": self.src_workspace_name,
                "new": self.trg_workspace_name.replace(".Workspace", ""),
            }
        )
        exclude = exclude + [self.src_workspace_name]

        for it in self.deployment_order:
            new_id = None
            name = it["name"]
            type = it.get("type")

            if name in exclude:
                continue

            if type in type_exclude:
                continue

            self.__deploy_item(name, None, it)

            for child in it.get("children", []):
                child_name = child["name"]
                self.__deploy_item(name, child_name, child)

    def __deploy_item(self, name, child=None, it=None):
        parent = ""
        cli_parameter = ""

        # Copy and replace IDs in the item
        tmp_path = self.copy_to_tmp(name, child, it.get("type"))

        if child is not None:
            parent = name
            name = child

        if ".KQLDatabase" in name:
            if child is not None:
                parent = (
                    parent
                    if self.eventhouse_name == "" or self.eventhouse_name is None
                    else f"{self.eventhouse_name}.Eventhouse"
                )
            if it["parent"] is not None:
                parent = (
                    it["parent"]
                    if self.eventhouse_name == "" or self.eventhouse_name is None
                    else f"{self.eventhouse_name}.Eventhouse"
                )
            self.mapping_table.append(
                {
                    "Type": "KQL DB Eventhouse",
                    "Item": name,
                    "old": it["parent"],
                    "new": parent,
                }
            )
            self.replace_kqldb_parent_eventhouse(tmp_path, parent)
        elif ".Eventhouse" in name:
            name = (
                name
                if self.eventhouse_name == "" or self.eventhouse_name is None
                else f"{self.eventhouse_name}.Eventhouse"
            )
        elif ".Eventstream" in name:
            self.replace_eventstream_destination(tmp_path, it.get("destinations"))
        elif ".Notebook" in name:
            cli_parameter = cli_parameter + " --format .py"
        elif ".DataPipeline" in name:
            self.replace_pipeline_parameter(tmp_path, it.get("parameters", []))
            self.replace_pipeline_activities(tmp_path, it.get("activities", []))
        elif ".SemanticModel" in name:
            self.replace_ids_in_folder(tmp_path, self.mapping_table)
        elif ".KQLDashboard" in name:
            self.replace_kqldashboard_datasources(tmp_path, it.get("datasources"))
        elif ".KQLQueryset" in name:
            self.replace_kqlqueryset_datasources(tmp_path, it.get("datasources"))
        elif ".Report" in name:
            self.replace_pbi_report_definition(tmp_path, it.get("datasource"))
        elif ".VariableLibrary" in name:
            self.add_variable_library_default(tmp_path, it.get("variables"))

        self.run_fab_command(
            f"import  /{self.trg_workspace_name}/{name} -i {tmp_path} -f {cli_parameter} ",
            silently_continue=True,
        )

        new_id = self.fab_get_id(name)

        if ".KQLDatabase" in name:
            self.mapping_table.append(
                {"Type": "KQL DB ID", "Item": name, "old": it["id"], "new": new_id}
            )
        elif ".Eventhouse" in name:
            query_uri = self.fab_get_kusto_query_uri(name)
            ingest_uri = self.fab_get_kusto_ingest_uri(name)
            self.mapping_table.append(
                {
                    "Type": "Kusto Query Uri",
                    "Item": name,
                    "old": it["kustoQueryUri"],
                    "new": query_uri,
                }
            )
            self.mapping_table.append(
                {
                    "Type": "Kusto Ingest Uri",
                    "Item": name,
                    "old": it["kustoIngestUri"],
                    "new": ingest_uri,
                }
            )
            self.mapping_table.append(
                {"Type": "Eventhouse ID", "Item": name, "old": it["id"], "new": new_id}
            )
        elif ".Eventstream" in name:
            for customEndpointName in it.get("customEndpointName", []):
                self.mapping_table.append(
                    {
                        "Type": "Connection String Eventstream",
                        "Item": name,
                        "old": customEndpointName,
                        "new": self.fab_get_eventstream_connection_string(
                            name, customEndpointName
                        ),
                    }
                )
            self.mapping_table.append(
                {"Type": "Eventstream ID", "Item": name, "old": it["id"], "new": new_id}
            )
        elif ".Notebook" in name:
            self.mapping_table.append(
                {"Type": "Notebook ID", "Item": name, "old": it["id"], "new": new_id}
            )
        elif ".DataPipeline" in name:
            self.mapping_table.append(
                {"Type": "Pipeline ID", "Item": name, "old": it["id"], "new": new_id}
            )
        elif ".Report" in name:
            self.mapping_table.append(
                {"Type": "Report ID", "Item": name, "old": it["id"], "new": new_id}
            )
        elif ".SemanticModel" in name:
            self.mapping_table.append(
                {
                    "Type": "Semantic Model ID",
                    "Item": name,
                    "old": it["id"],
                    "new": new_id,
                }
            )
        elif ".KQLDashboard" in name:
            self.mapping_table.append(
                {
                    "Type": "KQLDashboard ID",
                    "Item": name,
                    "old": it["id"],
                    "new": new_id,
                }
            )

        if it.get("folder") is not None:
            self.fab_update_item_folder(name, it.get("folder"))
