
from flask import current_app, Flask, Response
from ..core.responses import internal_server_error, forbidden_error ,make_response, not_found_error
from ..models.discovered_apis import DiscoveredAPIs
from ..util import serialize_clean_camel_case
from ..core.resources import Resource
import json
from ..vendor_specific import find_attribute_in_body, filter_apis_with_vendor_specific_params


class DiscoverApisOperations(Resource):

    def get_discoveredapis(self, api_invoker_id, query_params):

        services = self.db.get_col_by_name(self.db.service_api_descriptions)
        invokers = self.db.get_col_by_name(self.db.invoker_col)

        current_app.logger.debug("Discovering services apis by: " + api_invoker_id)

        try:
            invoker = invokers.find_one({"api_invoker_id": api_invoker_id})
            if invoker is None:
                current_app.logger.error("Api invoker not found in database")
                return not_found_error(detail="API Invoker does not exist", cause="API Invoker id not found")

            my_params = []
            my_query = {}
            # QPV = Query Parameter Value
            query_params_name = {
                "api_name": "api_name",
                "api_version": '{"aef_profiles": {"$elemMatch": {"versions" : {"$elemMatch": {"api_version": "QPV"}}}}}',
                "comm_type": '{"aef_profiles": {"$elemMatch": {"versions" : {"$elemMatch": {"resources": {"$elemMatch": {"comm_type":"QPV"}}}}}}}',
                "protocol": '{"aef_profiles": {"$elemMatch": {"protocol":"QPV"}}}',
                "aef_id": '{"aef_profiles": {"$elemMatch": {"aef_id":"QPV"}}}',
                "data_format": '{"aef_profiles": {"$elemMatch": {"data_format":"QPV"}}}',
                "api_cat": "service_api_category",
                "supported_features": "supported_features",
                "api_supported_features": "api_supp_feats"
            }

            vend_spec_query_params_n_values = {}
            for param in query_params:
                if query_params[param] is not None:
                    if "vend-spec" in param:
                        vend_param = param.split("vend-spec-")[1]
                        attribute_path = query_params[param]["target"].split('/')
                        vend_spec_query_params_n_values[attribute_path[1] + "." + vend_param] = query_params[param]["value"]
                    elif param in ["api_version", "comm_type", "protocol", "aef_id", "data_format"]:
                        my_params.append(json.loads(query_params_name[param].replace("QPV", query_params[param])))
                    else:
                        my_params.append({query_params_name[param]: query_params[param]})

            if my_params:
                my_query = {"$and": my_params}

            discoved_apis = services.find(my_query, {"_id":0})
            json_docs = []
            for discoved_api in discoved_apis:
                vendor_specific_fields_path = find_attribute_in_body(discoved_api, '')
                if vend_spec_query_params_n_values and vendor_specific_fields_path:
                    vs_filtered_apis = filter_apis_with_vendor_specific_params(discoved_api, vend_spec_query_params_n_values, vendor_specific_fields_path)
                    if vs_filtered_apis:
                        json_docs.append(vs_filtered_apis)
                else:
                    json_docs.append(discoved_api)

            if len(json_docs) == 0:
                return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions")

            apis_discovered = DiscoveredAPIs(service_api_descriptions=json_docs)
            res = make_response(object=serialize_clean_camel_case(apis_discovered), status=200)
            return res

        except Exception as e:
            exception = "An exception occurred in discover services"
            current_app.logger.error(exception + "::" + str(e))
            return internal_server_error(detail=exception, cause=str(e))

