import os
import base64
from datetime import datetime
from robot.api import logger
from accelarobotkeywords.runner import apiclient as api_clnt

HTTPPOST='POST'
HTTPGET='GET'
HTTPPUT='PUT'
HTTPPATCH='PATCH'

class TestrailIntegration: 
        
    def add_testrail_run(self, output_path, civic_platform_version, jenkins_build_number, test_rail_result_enabled, testrail_project_id, testrail_suite_id):
        is_success = None
        testrunid = None
        civp_version = os.getenv('JOB_NAME')
        if civp_version is None:
            civp_version=civic_platform_version
        enabledtestrail = str(test_rail_result_enabled)
        if enabledtestrail.lower() != 'true':
            print('TestRail Run is enabled on TestRail, No Action Taken')
            return is_success
        buildnumber = '#%s' % str(jenkins_build_number)
        testrail_file_dir = output_path
        testrail_file = os.path.join(testrail_file_dir,'testrail_run_id.txt')
        milestone_file = os.path.join(testrail_file_dir,'testrail_milestone_id.txt')
        print('Test rail test run path ' + testrail_file_dir)
        is_exits = os.path.isfile(testrail_file) and os.stat(testrail_file).st_size > 0
        if is_exits is not True:
            print('TestRail RunId file does not exists, creating new test rail run')
            now = datetime.now()
            dt_string = now.strftime("@ %m-%d-%Y %H:%M:%S")
            trail_num = dt_string
            if os.path.isfile(milestone_file) is False:
                milestone_id = self.create_testrail_milestone(civp_version, buildnumber, testrail_project_id, trail_num)
                with open(milestone_file, 'w') as writer:
                    writer.write(str(milestone_id))
            else:
                with open(milestone_file, 'r') as reader:
                    milestone_id = reader.readline()
            if milestone_id is not None:
                tc_ids = self.get_testrail_test_case_ids(civic_platform_version, testrail_project_id, testrail_suite_id)
                if tc_ids is None:
                    print('Get Test-rail IDs failed')
                    raise Exception
                if os.path.isfile(testrail_file) and os.stat(testrail_file).st_size > 0:
                    with open(testrail_file, 'r') as reader:
                        testrunid = reader.readline()
                else:
                    testrunid = self.create_testrail_testrun(civp_version, buildnumber, testrail_project_id, milestone_id, testrail_suite_id, tc_ids,trail_num)
                    with open(testrail_file, 'w') as writer:
                        writer.write(str(testrunid))
                    is_success = "TRUE"
            else:
                print('Failed to create milestone')
                raise Exception
        else:
            print('TestRail RunId file already exists, reading from file')
            with open(testrail_file, 'r') as reader:
                testrunid = reader.readline()
                print('Run Id From File: ' + str(testrunid))
    
        return testrunid

    def create_testrail_milestone(self, civp_version, deployment_environment, project_id, milestone_cnt):
        
        testrail_milestone_id = None
        test_rail_api_uri = self.get_tailrail_uri() + '/add_milestone/' + str(project_id)
        print(test_rail_api_uri)
        qparams = None
        milestone_name = civp_version + "-" + deployment_environment + "-" + str(milestone_cnt)
        body = '{"name": "' + milestone_name + '","description":"' + milestone_name + '"}'
        try:
            api_response = self.testrail_api(HTTPPOST, self.get_testrail_user(), self.get_testrail_user_password(), test_rail_api_uri, qparams, body)
            if api_response.status_code == 200:
                print(api_response)
                res_json = api_response.json()
                testrail_milestone_id = res_json['id']
                print("Milestone Id: " + str(testrail_milestone_id))
            else:
                print(api_response)
                res_json = api_response.json()
                print('Create Milestone in TestRail: Failed' + res_json)
                raise
        except Exception as e:
            print('Create Milestone in TestRail Failed')
            raise Exception(e)
        return testrail_milestone_id


    def create_testrail_testrun(self, civp_version, deployment_environment, project_id, milestone_id, test_suite_id, case_ids, testrun_cnt):
        
        testrail_testrun_id = None
        test_rail_api_uri = self.get_tailrail_uri() + '/add_run/' + str(project_id)
        print(test_rail_api_uri)
        qparams = None
        include_all = 'false'
        test_run_name = civp_version + "-" + deployment_environment + "-" + str(testrun_cnt)
        body = '{"suite_id":"' + str(test_suite_id) + '","name":"' + test_run_name + '","description":"' + test_run_name + '","milestone_id":"' + str(milestone_id) + '","include_all":' + str(include_all) + ',"case_ids":' + str(case_ids) + '}'
        try:
            api_response = self.testrail_api(HTTPPOST, self.get_testrail_user(), self.get_testrail_user_password(), test_rail_api_uri, qparams, body)
            if api_response.status_code == 200:
                print('Create TestRun in TestRail: Success')
                print(api_response)
                res_json = api_response.json()
                testrail_testrun_id = res_json['id']
                print("Milestone Id: " + str(testrail_testrun_id))
            else:
                print('Create Milestone in TestRail Failed')
                raise
        except Exception as e:
            print('Create Milestone in TestRail Failed')
            raise Exception(e)
        return testrail_testrun_id      


    def get_testrail_test_case_ids(self, civic_platform_version, project_id,test_suite_id):
        testrail_tc_ids = []
        civic_version = civic_platform_version
        test_rail_api_uri = self.get_tailrail_uri() + '/get_cases/' + str(project_id)
        print(test_rail_api_uri)
        qparams = 'suite_id=' + str(test_suite_id) + '&limit=250&offset=0'
        offsetnum=0
        body = None
        trautomationtype = 0
        if civic_version.lower().find('payment') > -1:
            trautomationtype = 1
        elif civic_version.lower().find('report') > -1:
            trautomationtype = 2
        elif civic_version.lower().find('classic') > -1:
            trautomationtype = 3
        elif civic_version.lower().find('acds') > -1:
            trautomationtype = 4
        try:
            api_response = self.testrail_api(HTTPGET, self.get_testrail_user(), self.get_testrail_user_password(), test_rail_api_uri, qparams, body)
            while api_response.status_code == 200:
                offsetnum+=250
                if len(api_response.json()['cases'])>0:
                    res_json = api_response.json()
                    for ids in res_json['cases']:
                        if civic_version.lower().find('mat') >= 0:
                            if ids['custom_robotautomated'] == 1 and ids['custom_mat'] == 1:
                                if civic_version.lower().find('aa') >= 0 and civic_version.lower().find('classic') < 0 and (ids['custom_automation_type'] == trautomationtype or ids['custom_automation_type'] == 3):
                                    testrail_tc_ids.append(ids['id'])
                                elif ids['custom_robotautomated'] == 1 and ids['custom_automation_type'] == trautomationtype:
                                    testrail_tc_ids.append(ids['id'])
                                else:   continue
                            else:   continue
                        elif civic_version.lower().find('acds') >= 0:
                            if ids['custom_robotautomated'] == 1 and ids['custom_automation_type'] == trautomationtype:
                                testrail_tc_ids.append(ids['id'])
                            else:   continue
                        elif civic_version.lower().find('aa') >= 0 and civic_version.lower().find('classic') < 0:
                            if ids['custom_robotautomated'] == 1 and (ids['custom_automation_type'] == trautomationtype or ids['custom_automation_type'] == 3):
                                testrail_tc_ids.append(ids['id'])
                            else:   continue
                        else:
                            if ids['custom_robotautomated'] == 1 and ids['custom_automation_type'] == trautomationtype:
                                testrail_tc_ids.append(ids['id'])
                            else:   continue
                else:
                    break
                qparams = 'suite_id=' + str(test_suite_id) + '&limit=250&offset=' + str(offsetnum)
                api_response = self.testrail_api(HTTPGET, self.get_testrail_user(), self.get_testrail_user_password(), test_rail_api_uri, qparams, body)
            if api_response.status_code != 200:
                print('Get test Cases from TestRail API Failed with error')
                raise
        except Exception as e:
            print('Get test Cases from TestRail failed')
            raise Exception(e)
        return testrail_tc_ids
    
    def testrail_api(self, http_method, testrail_user, testrail_user_pwd, uri, query_params, request_body):
        res_body = None
        res = None
        auth = str(
                base64.b64encode(
                    bytes('%s:%s' % (testrail_user, testrail_user_pwd), 'utf-8')), 'ascii').strip()
        headers = {'Authorization': 'Basic ' + auth}
    
        if http_method == HTTPPOST or http_method == HTTPGET:
            headers['Content-Type'] = 'application/json'
        try:
            logger.info(request_body)
            res = api_clnt.apirequest(http_method, uri, headers, query_params, request_body)
            if res.status_code == 200:
                res_body = res
            else:
                logger.error("Update Test Case  API failed " + str(request_body) + str(res))
                res_body = None
        except Exception as e:
            logger.error("Error in taro_execute_api method  : %s" % str(e))
            raise e
        return res_body
    
    def get_tailrail_uri(self):
        test_rail_uri = 'https://accela.testrail.com/index.php?/api/v2'
        return test_rail_uri


    def get_testrail_user(self):
        test_rail_user = 'mvishwanath99@accela.com'
        return test_rail_user


    def get_testrail_user_password(self):
        test_rail_user_password = 'autotest'
        return test_rail_user_password
        
        