from logging import raiseExceptions
import os
import traceback

from flask import Blueprint, request
from flask.helpers import send_from_directory

from scripts.config.app_constants import *
from scripts.core.handler.pipeline.pipeline_handler import PipelineHandler

# from scripts.services.login.login import login_required
from scripts.utils.AESEnc import apply_encryption
from scripts.logging.logger import logger

flow_diagram_blueprint = Blueprint("flow_diagram_configuration", __name__)


@flow_diagram_blueprint.route(Endpoints.api_create, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def create_flow_configuration():
    """
    This is the service to create new alarm_priority_type in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().create_record(input_data)
        return_json = PipelineHandler().create_record(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": str(e), "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_list, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def get_flow_list_configuration():
    """
    This method is to fetch the pipeline list
    """
    try:
        input_data = request.data
        return_json = PipelineHandler().get_record_list(input_data)
        return return_json
    except Exception as e:
        logger.exception(str(e))
        traceback.print_exc()
        return {"status": "failed", "message": "Failed to list pipelines"}


@flow_diagram_blueprint.route(Endpoints.api_delete, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def delete_flow_configuration():
    """
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        return_json = PipelineHandler().delete_pipeline(input_data, request)
        return return_json
    except Exception as e:
        logger.exception()
        traceback.print_exc()
        return {"status": "failed", "message": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_get, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def get_flow_configuration():
    """
    This service will get all alarm_priority_type details from user collection in elmeasure database in mongodb
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # input_data = request.get_json()
        # return_json = FlowConfigurationHandler().get_record(input_data)
        return_json = PipelineHandler().get_record(input_data)
        return return_json
    except Exception as e:
        logger.exception("alarm_enable_disable" + str(e))
        traceback.print_exc()
        return {"status": "failed", "message": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_load_nodes, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def load_nodes():
    """
    This is the service to create new alarm_priority_type in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().load_nodes(input_data)
        return_json = PipelineHandler().load_nodes(input_data)

        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.create_node, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def create_nodes():
    """
    This is the service to create new custom node in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().create_nodes(input_data)
        return_json = PipelineHandler().create_nodes(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.get_template, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def get_template_for_node():
    """
    This is the service to create new custom node in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().get_template(input_data)
        return_json = PipelineHandler().get_template(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.fetch_node, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def fetch_nodes():
    """
    This is the service to create fetch existing nodes in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().fetch_nodes(input_data)
        return_json = PipelineHandler().fetch_nodes(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.job_list, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def jobs_list():
    """
    This is the service to list jobs in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        return_json = PipelineHandler().jobs_list(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.delete_node, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def delete_nodes():
    """
    This is the service to create new custom node in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().delete_node(input_data)
        return_json = PipelineHandler().delete_node(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.get_job_log, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def get_log_for_job():
    """
    This is the service to create new custom node in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().get_job_log(input_data)
        return_json = PipelineHandler().get_job_log(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_get_deployment_logs, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def get_deployment_log_for_job():
    """
    This is the service to create new custom node in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        return_json = PipelineHandler().get_deployment_job_log(input_data)
        return return_json
    except Exception as e:
        traceback.print_exc()
        logger.exception(str(e))
        return {"status": "failed", "message": "Name already exist.!!", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_build, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def build_pipeline():
    """
    This is the service to create new build for the pipeline in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        return_json = PipelineHandler().create_build(input_data)
        return return_json
    except Exception as e:
        logger.exception(" exception occurred while creating a build for the pipeline:" + str(e))
        return {"status": "failed", "message": "unable to create build. {}".format(str(e)), "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_get_deployment_config, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def get_pipeline_debug_topic_mapping():
    """
    This is the service to create new build for the pipeline in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().get_topic_mapping_for_a_pipeline_nodes(input_data)
        return_json = PipelineHandler().get_topic_mapping_for_a_pipeline_nodes(input_data)
        return return_json
    except Exception as e:
        logger.exception(" exception occurred while fetching the pipeline deployment configuration:" + str(e))
        return {"status": "failed", "message": "Unable to get the deployment configuration for the pipeline",
                "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_save_node_custom_config, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def save_node_custom_config():
    """
    This is the service to create new build for the pipeline in the portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().save_custom_node_configurations(input_data)
        return_json = PipelineHandler().save_custom_node_configurations(input_data)
        return return_json
    except Exception as e:
        logger.exception("Failed to save custom node configurations" + str(e))
        return {"status": "failed", "message": "Failed to save the node configurations", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_category_all, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def save_category():
    """
    This service is create a new category in the pipeline portal
    :return: Base64 encoded JSON with status success or failed
    """
    try:
        input_data = request.data
        return_json = PipelineHandler().all_operation_on_categories(input_data)
        return return_json
    except Exception as e:
        logger.exception("Failed to save pipeline category" + str(e))
        return {"status": "failed", "message": "Failed to perform category operation ", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_category_list, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def list_category():
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().list_pipeline_categories(input_data)
        return_json = PipelineHandler().list_pipeline_categories(input_data)
        return return_json
    except Exception as e:
        logger.exception("Failed to save pipeline category" + str(e))
        return {"status": "failed", "message": "Failed to list categories ", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_list_components, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def list_components():
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().list_pipeline_components(input_data)
        return_json = PipelineHandler().list_pipeline_components(input_data)
        return return_json
    except Exception as e:
        logger.exception("Failed to save pipeline category" + str(e))
        return {"status": "failed", "message": "Failed to list components ", "detail": str(e)}


@flow_diagram_blueprint.route(Endpoints.api_make_component_public, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def make_component_public():
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().make_component_public(input_data)
        return_json = PipelineHandler().make_component_public(input_data)
        return return_json
    except Exception as e:
        logger.exception("Exception while making component public :" + str(e))
        return {"status": "failed", "message": "Failed to make a component public"}


@flow_diagram_blueprint.route(Endpoints.api_load_categories, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def fetch_pipeline_categories():
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().get_pipeline_category(input_data)
        return_json = PipelineHandler().get_pipeline_category(input_data)
        return return_json
    except Exception as e:
        logger.exception("Exception loading pipeline categories :" + str(e))
        return {"status": "failed", "message": "Failed to load pipeline categories"}


@flow_diagram_blueprint.route(Endpoints.api_create_new_pipeline_instance, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def create_new_pipeline_instance():
    try:
        input_data = request.data
        # return_json = FlowConfigurationHandler().get_pipeline_category(input_data)
        return_json = PipelineHandler().create_new_pipeline_instance(input_data)
        return return_json
    except Exception as e:
        logger.exception("Error occurred while creating a new pipeline instance :" + str(e))
        return {"status": "failed", "message": "Failed to create a new pipeline instance"}


@flow_diagram_blueprint.route(Endpoints.api_create_pipeline_options, methods=[RequestMethods.POST])
# @login_required
# @apply_encryption
def create_pipeline_options():
    try:
        input_data = request.data
        return_json = PipelineHandler().create_pipeline_options()
        return return_json
    except Exception as e:
        logger.exception("Error occurred while creating a new pipeline instance :" + str(e))
        return {"status": "failed", "message": "Failed to create a new pipeline instance"}


@flow_diagram_blueprint.route(Endpoints.api_download_win_build, methods=[RequestMethods.POST])
# @login_required
@apply_encryption
def download_build():
    try:
        input_data = request.get_json()
        dirc = input_data.get('pipeline_id')
        ver = input_data.get("version")
        if dir and ver:
            resp = send_from_directory(directory=f"/opt/services/data_processor/ilens/{dirc}", filename=f"v{ver}.zip", as_attachment=True)
        else:
            raise Exception
        return resp
    except Exception as e:
        logger.exception("Error occurred while creating a new pipeline instance :" + str(e))
        return {"status": "failed", "message": "Failed - File no found"}
