from db import direct_query
import os
from db.query import QueryExecution
from utilities.schema_loader import SchemaLoad
from authentication import AuthenticationSchema
from rules_aggregator import RulesAggregator
from data_persistence import DataPersistence
from dry_run_function import DryRunFunction
from schema_validation import SchemaLoading
import json
from response.response_generation import ResponseGeneration
from helper_functions import set_data
from logger_module.package_logger import print_log


class APIWrapper:

    def __init__(self, request):
        self.request = request

    def main(self):
        if self.request.method == 'POST':
            print_log(self.request.get_json(force=True))
        else:
            print_log(self.request.get_json)
        host_name = self.request.headers.get("Host", "").split(".")[0]
        # Fallback for local testing if needed
        if host_name in ['localhost', '127', '']:
            host_name = self.request.headers.get("X-Custom-Host", 'mconnectuat')
        if 'lending' in host_name:
            from vendor_authentication import VendorAuthenticationSchema
            auth_status, auth_details = VendorAuthenticationSchema().auth(self.request, host_name)
        else:
            auth_status, auth_details = AuthenticationSchema().auth(self.request)
            
        if auth_status:
            path = self.schema_path_creation(auth_details)
            schema_body = self.schema_loading_from_bucket(path)
            response_controller = ResponseGeneration(schema_body, auth_details.get('endpoint'), auth_details.get('method'))
            if schema_body:
                function_result = DryRunFunction(schema_body, auth_details.get('endpoint'), auth_details.get('method')).main('functions', 'init')
                validation_response = SchemaLoading.schema_validation(schema_body, auth_details.get('endpoint'),auth_details.get('method'))
                if validation_response.get('cf_code') == 'CF200':
                    response = RulesAggregator(self.request, schema_body, auth_details.get('endpoint')).main()
                    if response.get('cf_code') == 'CF200':
                        function_result = DryRunFunction(schema_body, auth_details.get('endpoint'), auth_details.get('method')).main('functions')
                        if function_result.get('cf_code') == 'CF200':
                            result = DataPersistence(self.request, schema_body, auth_details.get('endpoint')).main()
                            if result.get('cf_code') == 'CF200':
                                return response_controller.generate_response(result.get('cf_code'))
                        else:
                            return response_controller.generate_response(function_result.get('cf_code'), )
                    else:
                        return response_controller.generate_response(response.get('cf_code'))
                elif validation_response.get('cf_code') == 'CF500':
                    return response_controller.generate_response('CF500')
                else:
                    return response_controller.generate_response(validation_response.get('cf_code'), )
        else:
            return auth_details.get('application/json'), int(auth_details.get('status_code'))

    @staticmethod
    def schema_path_creation(data_dict):
        try:
            domain_path = data_dict.get('domain').split(".")
            app_domain = domain_path[0]
            print_log(f'Domain: {app_domain}')
            # app_domain = 'mconnectuat'
            if data_dict.get('source') == 'admin':
                return f"api_wrapper/{data_dict.get('source')}/{app_domain}/category/default/default.json"
            if data_dict.get('category_id') == os.environ.get('SOLAR_CATEGORY_ID'):
                state, file_name = QueryExecution.fetch_result(direct_query.file_merchant, (data_dict.get('category_id'),))
                category_name = file_name.get('name').split()
                category_word = ('_'.join(category_name)).lower()
            else:
                data_dict['category_id'] = 'default'
                category_word = 'default'
            category_bucket_path = f"api_wrapper/category/{data_dict.get('category_id')}/" + app_domain + f"/{category_word}.json"
            merchant_name_split = data_dict.get('merchant_name').split()
            merchant_word = ('_'.join(merchant_name_split)).lower()
            if 'lending' in app_domain:
                vendor_id = data_dict.get('vendor_id') or data_dict.get('merchant_id')
                merchant_bucket_path = f"api_wrapper/vendor/{vendor_id}/" + app_domain + f"/{merchant_word}.json"
            else:
                merchant_bucket_path = f"api_wrapper/merchant/{data_dict.get('merchant_id')}/" + app_domain + f"/{merchant_word}.json"
            # category_bucket_path = 'api_wrapper/category/6/mconnectuat/solar_rooftop_panel.json'
            file_exists = SchemaLoad.s3_check_exists(merchant_bucket_path)
            if file_exists:
                print_log('Merchant Level Schema Selected')
                print_log(merchant_bucket_path)
                set_data('schema_path', merchant_bucket_path)
                return merchant_bucket_path
            else:
                file_exists = SchemaLoad.s3_check_exists(category_bucket_path)
                if file_exists:
                    print_log('Category Level Schema Selected')
                    print_log(category_bucket_path)
                    set_data('schema_path', category_bucket_path)
                    return category_bucket_path
        except Exception as ex:
            print_log(str(ex))

    @staticmethod
    def schema_loading_from_bucket(bucket_path):
        body = SchemaLoad.s3_read_file(bucket_path)
        # with open('JSON/merchant/6601/mconnect/solarsquare_energy_private_limited.json', 'r') as f:
        #     return json.load(f)
        return json.loads(body)
