""" Import data and transform it."""

import pandas as pd
import requests, json, ast
import numpy as np
from time import sleep

# Basic Authentication using API Token
session = requests.Session()
session.headers = {'Content-Type': 'application/json', 'Authorization': 'Basic dGFwYXMuZzkxQGdtYWlsLmNvbS90b2tlbjoxTkFMaUE1U3BoTEo5cmxrQkJ1WkNGWlhqWFZ2YmZtQ0hBUFczTlZI'}


class Npencoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.int64):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        elif isinstance(obj, np.bool_):
            return super(Npencoder, self).encode(bool(obj))
        else:
            return super(Npencoder, self).default(obj)


#Organization Data:

org_df = pd.read_csv('C:/Users/guptata/Downloads/pfd_testmaterials/organizations.csv')


org_df['domain_names'] = org_df['domain_names'].map(lambda x: str(x).replace('(', '').replace(')', '').replace('_', '.'))

org_df['id'] = org_df['id'].astype(np.int64).astype(str)

org_mapping = dict(zip(org_df['id'], org_df['name']))
old_new_org_dict = dict(zip(org_df.id,org_df.z_org_id))


def load_organizations():
	org_df = org_df.replace({np.nan: None})
	org_df['id'] = org_df['id'].astype(np.int64).astype(str)
	id_list=[] # To store org id generated by API
	for i in range(len(org_df)):
    
		payload = { "organization": {
                                    "name": org_df.loc[i, "name"],
                                    "domain_names": ast.literal_eval(org_df.loc[i, "domain_names"]),
                                    "details": org_df.loc[i, "details"],
                                    "notes": org_df.loc[i, "notes"],
                                    "tags": ast.literal_eval(org_df.loc[i, "tags"]),
                                    "organization_fields": {
                                        "region": org_df.loc[i, "merchant_id"],
                                        "creator": "tapas"
                                    }
                                    }
                  }
        url = 'https://z3nplatformdevtg.zendesk.com/api/v2/organizations.json'
        response = session.post(url, data=json.dumps(payload))
        if response.status_code != 201:
            print('Organization Import failed with {}'.format(response.text))
            exit()
        id_list.append(json.loads(response.text)['organization']['id'])
    
    # Adding new org id to dataframe column
    org_df['z_org_id'] = id_list 
    #org_df.to_csv('C:/Users/guptata/Downloads/pfd_testmaterials/new_org.csv', index=False)
-------------------------------------------------------------------------------------------------------------------------------

# Users Data

old_new_org_dict = dict(zip(org_df.id,org_df.z_org_id))
users_df = pd.read_csv('C:/Users/guptata/Downloads/pfd_testmaterials/users.csv')

z_org_list=[] # To store new org name

# org_name will be actual org name seperated by '|' for list values and new org id if it exists else None
for j, row in users_df.iterrows():
    if str(row['organization_id'])[0] != '[':
#        users_df.loc[j, 'org_name'] = org_mapping.get(str(row.get('organization_id', None)), None)
        z_org_list.append(old_new_org_dict.get(row['organization_id'], None))
    else:
        org_list = ast.literal_eval(row['organization_id'])
        org_name_list = [org_mapping.get(d, d) for d in org_list]
        z_org_list.append(old_new_org_dict.get(org_list[0], org_list[0]))
        users_df.loc[j, 'org_name'] = '| '.join(org_name_list)
users_df['z_org'] = z_org_list		
			
users_df = users_df.sort_values('email')
users_df.drop_duplicates(subset='email', inplace=True, keep="first")
users_df= users_df.reset_index(drop=True)

def load_users():
    z_user_id = []
    users_dict = {'users': []}
    payloads=[]

    users_df=users_df.replace({np.nan: None})
    users_df.replace('true', 'True')
    users_df['notes'] = users_df['notes'].astype('str')

    for i in range(len(users_df)):
        users_dict['users'].append(
            {
                'email': users_df.loc[i, "email"],
                'name': users_df.loc[i, "name"],
                'organization_id': users_df.loc[i, "z_org"],
                'role': users_df.loc[i, "role"],
                'external_id': users_df.loc[i, "id"],
                'active': users_df.loc[i, "active"],
                'notes': users_df.loc[i, "notes"],
                'tags': users_df.loc[i, "tags"],
                'user_fields': {
                                "employee_id": users_df.loc[i, "employee_id"],
                                "subscription": users_df.loc[i, "api_subscription"],
                                "group": users_df.loc[i, "group"],
                                "promotion_code": users_df.loc[i, "promotion_code"],
                                "organization": users_df.loc[i, "org_name"],
                                'creator': 'tapas'
                                }
            })
        if len(users_dict['users']) == 100:

            # Creating batch of 100 rows in a list
            payloads.append(json.dumps(users_dict, cls=Npencoder))
            users_dict = {'users': []}

    if users_dict['users']:
        payloads.append(json.dumps(users_dict, cls=Npencoder))
        
    url = 'https://z3nplatformdevtg.zendesk.com/api/v2/users/create_many.json'

    for payload in payloads:
        #print(payload)
        response = session.post(url, data=payload)
        print(response.text)
        #z_user_id.append(json.loads(response.text)['users']['id'])
        
        if response.status_code != 201:
            print('Users Import failed with status {}'.format(response.status_code))
            exit()
        print('Successfully imported a batch of users.')
-------------------------------------------------------------------------------------------------------------------------------

# Tickets Data
tickets_df = pd.read_csv('C:/Users/guptata/Downloads/pfd_testmaterials/tickets.csv')

z_status = {'new': 'New', 'open': 'Open', 'assigned': 'Open', 'waiting':    'Pending', 'external': 'On-Hold', 'engineering': 'On-Hold', 'resolved': 'Solved', 'done': 'Closed', 'retracted': 'Closed'}

tickets_df['status']= tickets_df['status'].map(z_status)
tickets_df=tickets_df.replace({np.nan: None})
tickets_df.replace('true', 'True')

tickets_df['assignee_id'] = tickets_df['assignee_id'].astype('Int64')

#Create a map for old and new user id
url = 'https://z3nplatformdevtg.zendesk.com/api/v2/users.json'
response=session.get(url)
users_list = json.loads(response.text)['users']
old_new_user_id_dict = {}
for i in users_list:
    old_new_user_id_dict[i['external_id']] = i['id']
#print(old_new_user_id_dict)

def load_tickets():

    payloads = []
    tickets_dict = {'tickets': []}
    # Substituting old ids with new ids in assignee_id, submitter_id and requester_id
    for i in range(len(tickets_df)):
        tickets_dict['tickets'].append(
                {   'comment': {"body":tickets_df.loc[i, "description"]},
                    'assignee_id': old_new_user_id_dict.get(tickets_df.loc[i, "assignee_id"], None),
                    'created_at': tickets_df.loc[i, "created_at"],
                    'subject': tickets_df.loc[i, "subject"],
                    'status': tickets_df.loc[i, "status"],
                    'submitter_id': old_new_user_id_dict.get(tickets_df.loc[i, "submitter_id"], None),
                    'requester_id': old_new_user_id_dict.get(tickets_df.loc[i, "requester_id"], None),
                    'updated_at': tickets_df.loc[i, "updated_at"],
                    'due_at': tickets_df.loc[i, "due_at"],
                    'tags': tickets_df.loc[i, "tags"],
                    'custom_fields': [{
                                    'id': 360006453496,
                                    'value': tickets_df.loc[i, "business name"]},
                                    {
                                    'id': 360006424135,
                                    'value': tickets_df.loc[i, "dept"]},
                                    {
                                    'id': 360006453476,
                                    'value': tickets_df.loc[i, "emp id"]},
                                    {
                                    'id': 360006424155,
                                    'value': tickets_df.loc[i, "product information"]},
                                    {
                                    'id': 360006424175,
                                    'value': tickets_df.loc[i, "start date"]},
                                    {
                                    'id': 360006424195,
                                    'value': tickets_df.loc[i, "subscription"]},
                                    {
                                    'id': 360006424215,
                                    'value': tickets_df.loc[i, "about"]},
                                    {
                                    'id': 360006453516,
                                    'value': 'tapas'}]
                })
        if len(tickets_dict['tickets']) == 100:
            #print(tickets_dict)
            # Creating batch of 100 rows in a list
            payloads.append(json.dumps(tickets_dict, cls=Npencoder))
            tickets_dict = {'tickets': []}

    if tickets_dict['tickets']:
        payloads.append(json.dumps(tickets_dict, cls=Npencoder))

    url = 'https://z3nplatformdevtg.zendesk.com/api/v2/imports/tickets/create_many.json'

    def call_ticket_api(payload):
        response = session.post(url, data=payload)
        print(response.text)
        #z_user_id.append(json.loads(response.text)['users']['id'])
        
        if response.status_code == 429:
            
            print('Rate Limit reached. Sleeping for 120 sec..!')
            sleep(120)
            call_ticket_api(payload)
                
    for payload in payloads:
        #print(payload)
        
        call_ticket_api(payload)
        print('Successfully imported a batch of tickets.')



if __name__ == '__main__':
    load_organizations()
    load_users()
    load_tickets()