import urllib.request
import urllib.parse
import json
import time

BASE_URL = "http://127.0.0.1:8080/leads_collection_webhook.php"

def run_test(name, payload, expected_status, check_func=None):
    print(f"Running Test: {name} ...", end=" ")
    try:
        data = urllib.parse.urlencode(payload).encode()
        req = urllib.request.Request(BASE_URL, data=data, method='POST')
        
        # Add headers specifically for urlencoded form data
        req.add_header('Content-Type', 'application/x-www-form-urlencoded')

        with urllib.request.urlopen(req) as response:
            status_code = response.getcode()
            response_body = response.read().decode()
            
            try:
                json_body = json.loads(response_body)
            except json.JSONDecodeError:
                json_body = {"raw": response_body}

            if status_code != expected_status:
                print(f"FAILED. Expected status {expected_status}, got {status_code}")
                print(f"Response: {response_body}")
                return

            if check_func:
                if check_func(json_body):
                    print("PASSED")
                else:
                    print("FAILED. Custom check failed.")
                    print(f"Response: {json.dumps(json_body, indent=2)}")
            else:
                print("PASSED")

    except urllib.error.HTTPError as e:
        if e.code == expected_status:
             # If we expected an error (like 400) and got it, that's a pass, but we might want to check the body
             response_body = e.read().decode()
             try:
                 json_body = json.loads(response_body)
             except:
                 json_body = {"raw": response_body}
             
             if check_func:
                 if check_func(json_body):
                     print("PASSED")
                 else:
                     print("FAILED. Custom check failed.")
                     print(f"Response: {json.dumps(json_body, indent=2)}")
             else:
                 print("PASSED")
        else:
            print(f"FAILED. HTTPError: {e.code}")
            print(e.read().decode())
    except Exception as e:
        print(f"FAILED. Exception: {e}")

# --- Test Cases ---

def check_error_message(json_body):
    return "message" in json_body and "Required POST variable" in json_body["message"]

def check_token_present(json_body):
    return "data" in json_body and "onboarding_link" in json_body["data"] and "token=" in json_body["data"]["onboarding_link"]

def check_new_user_welcome(json_body):
    data = json_body.get("data", {})
    return data.get("should_send_welcome") is True and data.get("is_registered") is False

def check_registered_no_welcome(json_body):
    data = json_body.get("data", {})
    # It might be registered but should_send_welcome should be False
    return data.get("is_registered") is True and data.get("should_send_welcome") is False

# 1. Missing Fields
run_test("Missing whatsappNumber", {}, 400, check_error_message)

# 2. New User (Organic) - Random number to ensure it's new
import random
rand_suffix = random.randint(10000, 99999)
new_user_phone = f"9230000{rand_suffix}"

run_test("New User (Organic)", {
    "whatsappNumber": new_user_phone,
    "source": "organic",
    "messageText": "Hello organic"
}, 200, check_new_user_welcome)

# 3. New User (Ad Source)
rand_suffix_2 = random.randint(10000, 99999)
ad_user_phone = f"9231111{rand_suffix_2}"
run_test("New User (Ad Source)", {
    "whatsappNumber": ad_user_phone,
    "source": "meta_ad",
    "campaignId": "test_camp_1"
}, 200, check_new_user_welcome)

# 4. Existing Registered User
# We need a user that actually exists. I will assume '923001234567' exists or I needs to mock it.
# To be safe, I should try to INSERT a user first if I could, but I can't easily accessing DB directly from this script without pymongo.
# However, I can look at the output of the view_file I did earlier or just creating a lead that becomes registered.
# For now, let's rely on the previous run. If I run the same number again, it should still be "New User" because I didn't register it in `users` collection, only in `leads`.
# So, re-running test 2 should result in 'should_send_welcome' = False if the gap logic works and it knows it's an existing lead!

# Let's test the "Engagement Only" logic (Test 5) by using the SAME number from Test 2.
# Since we just messaged, the gap is 0. So expected welcome should be FALSE.
print("\n--- Re-using Organic User for Engagement Check ---")
run_test("Existing Lead (Recent)", {
    "whatsappNumber": new_user_phone,
    "source": "organic",
    "messageText": "Hello again"
}, 200, lambda b: b["data"]["should_send_welcome"] is False)

# To test "Registered User", I really need a registered user.
# I will try to hit `create_account.php` first to create one? 
# I can try to use `create_account.php` via this script too!

print("\n--- Creating a Real Registered User ---")
reg_phone = f"9232222{random.randint(10000,99999)}"
# Register this user
reg_payload = {
    "accRegName": "Test User",
    "phoneNumber": reg_phone,
    "whatsappNumber": reg_phone,
    "registrationMethod": "website"
}
# Call create_account.php
try:
    data = urllib.parse.urlencode(reg_payload).encode()
    req = urllib.request.Request("http://127.0.0.1:8080/create_account.php", data=data, method='POST')
    req.add_header('Content-Type', 'application/x-www-form-urlencoded')
    with urllib.request.urlopen(req) as resp:
        if resp.getcode() == 201:
            print(f"Registered user {reg_phone} successfully.")
            # Now test webhook
            run_test("Registered User Webhook", {
                "whatsappNumber": reg_phone,
                "source": "organic"
            }, 200, check_registered_no_welcome)
        else:
            print("Failed to register user to set up test.")
except Exception as e:
    print(f"Registration setup failed: {e}")

