"""Checks concerning (usually renku) datasets"""

from renku.api import Activity, Project, Dataset
from omnibenchmark.renku_commands import renku_api
from omnibenchmark.utils.user_input_checks import flatten
import requests
from typing import Union, List, Mapping, Any
import os


def query_renku_api(
    url: str, page_num: int, page_item: int = 100
) -> List[Mapping[Any, Any]]:
    response = requests.get(url, params={"per_page": page_item, "page": page_num})
    return response.json()


def query_multipages(url: str, page_item: int = 100) -> List[Mapping[Any, Any]]:
    multi_page = True
    page_num = 1
    response: List = []
    while multi_page:
        res = query_renku_api(url, page_num=page_num, page_item=page_item)
        page_num += 1
        if len(res) < page_item:
            multi_page = False
        if isinstance(res, list):
            response.extend(res)
    return response


def renku_dataset_exist(name: str, path: Union[os.PathLike, str] = os.getcwd()) -> bool:
    """Check if a renku dataset with a specific name already exist at a certain project path.

    Args:
        name (str): Dataset name
        path (PathLike, optional): Project path to check. Defaults to ".".

    Returns:
        bool: True/False a dataset with that name exist in the project at that path.
    """

    current_dir = os.getcwd()
    os.chdir(path)
    datasets = renku_api.renku_dataset_list()
    # datasets = Dataset.list()
    matches = [dataset.name for dataset in datasets if dataset.name == name]
    os.chdir(current_dir)
    return True if len(matches) >= 1 else False


def dataset_name_exist(name: str, kg_url: str) -> bool:
    """Check if a renku dataset with a defined name already exists in the knowledge base.

    Args:
        name (str): Name to query
        kg_url (str): Url of the knowledge base to query

    Returns:
        bool: True/False, if a dataset with that name already exist
    """

    url = kg_url + "/datasets?query=" + name
    response = query_multipages(url)
    # Checks to ensure no complete name matching (Remove if file matching is moved to triplet store queries)
    if any(name in item["name"] for item in response) or any(
        item["name"] in name for item in response
    ):
        nl = "\n"
        name_list = set([item["name"] for item in response])
        print(
            f"A dataset with a complete match of {name} already exist.\n"
            "Please specify a name without a complete match within:\n"
            f"{nl}{nl.join(name_list)}"
        )
        return True
    return True if name in [item["name"] for item in response] else False


def find_activities_with_missing_inputs() -> List[Activity]:
    """Find activities related to missing input files

    Returns:
        List[Activity]: Activities that have missing input files linked
    """
    (
        outdated_generations,
        outdated_activities,
        modified_inputs,
        deleted_inputs,
    ) = Project().status()
    return Activity.filter(inputs=list(deleted_inputs))


def find_outputs_with_missing_inputs() -> List[str]:
    """Find Outputs that were generated by activities with missing inputs

    Returns:
        List[str]: List of output files, that have missing input files
    """
    act_list = find_activities_with_missing_inputs()
    out_list = flatten([act.generated_outputs for act in act_list])
    return list(set([out.path for out in out_list]))
