import os
import km3db
import json
import subprocess
import shutil

from snakemake.logging import logger
from snakemake.shell import shell

from .bookkeeping import bookkeep_inputs


def generate_iRods_profile(
    filename, host="ccirods.in2p3.fr", port=5530, zone_name="in2p3"
):
    """Generate json configuration file for iRods"""
    config = {
        "irods_home": "/in2p3/km3net",
        "irods_host": host,
        "irods_port": port,
        "irods_zone_name": zone_name,
    }

    json_object = json.dumps(config, indent=4)

    logger.info("irods json configuration generated:")
    logger.info(json_object)

    with open(filename, "w") as f:
        f.write(json_object)


def is_resource_needed(workflow, resource):
    """Check if the given resources appears in a job that will be run"""
    jobs = [
        jobs.name
        for jobs in workflow.persistence.dag.needrun_jobs()
        if resource in jobs.resources.keys()
    ]
    logger.debug(f"Jobs requiring {resource}: {jobs}")
    return len(jobs) > 0


def check_ressources_availability(workflow, config):
    """Check KM3NeT ressources access from the current session"""
    km3net_db_need = is_resource_needed(workflow, "km3net_db_socket")
    km3net_gitlab_need = is_resource_needed(workflow, "km3net_gitlab_socket")
    irods_need = is_resource_needed(workflow, "irods_socket")

    try:
        # DB access
        if km3net_db_need:
            logger.info("Check DB access and cookie validity ...")
            sds = km3db.tools.StreamDS()
            if "DBCOOKIE" not in os.environ:
                # DBCOOKIE is needed to provide loggin information within JPP container
                # to get the default PMT parameters from the DB
                logger.info("Exporting cookie to environement variable DBCOOKIE ...")
                os.environ["DBCOOKIE"] = km3db.DBManager().session_cookie
                shutil.copy2(km3db.core.COOKIE_FILENAME, "./")
        else:
            logger.info(
                "No jobs requiring DB socket in the DAG, skip the cookie check."
            )

        if irods_need:
            # iRods credentials
            logger.info("Check iRods credentialds ...")

            # Check if a container is provided
            container = None
            if "irods" in config:
                if "container" in config["irods"]:
                    container = config["irods"]["container"]

            if os.path.exists(".irods/.irodsA") == False:
                os.makedirs(".irods", exist_ok=True)
                logger.info("Create iRods configuration files ...")
                generate_iRods_profile(".irods/irods_environment.json")
                # Call iinit from the container to create the cookie
                try:
                    shell(
                        """
                        cd $HOME
                        HOME="./"
                        iinit
                        """,
                        container_img=container,
                        apptainer_args=workflow.deployment_settings.apptainer_args,
                    )

                except subprocess.CalledProcessError as E:
                    logger.error(
                        "Error when trying call iinit. Maybe a wrong iRods password ?"
                    )
                    os.remove(".irods/.irodsA")
                    raise E
        else:
            logger.info(
                "No jobs requiring iRods in the DAG, skip the credential check."
            )
        # ssh ready for git.km3net.de
        if km3net_gitlab_need:
            logger.info("Check ssh connection with git.km3net.de ...")
            shell("ssh -T git@git.km3net.de")
        else:
            logger.info(
                "No jobs requiring km3net gitlab socket in the DAG, skip the connectivity check."
            )

    except Exception as E:
        logger.error("Failed, exit")
        raise E


def default(workflow, config):
    """Wrapper for onstart action"""

    logger.info("-" * 20 + " On start checks " + "-" * 20)

    check_ressources_availability(workflow, config)

    logger.info("-" * 20 + "    Completed    " + "-" * 20)


def default_rbdp(workflow, config):
    """Wrapper for onstart action in run-based data-processing context"""

    logger.info("-" * 20 + " On start checks " + "-" * 20)

    check_ressources_availability(workflow, config)
    bookkeep_inputs(workflow, config)

    logger.info("-" * 20 + "    Completed    " + "-" * 20)
