"""
Standalone script to register M-Pesa C2B callback URLs
Can be run independently without Django

Usage:
    python register_mpesa_urls_standalone.py

You can also use this with Postman by following the steps below.
"""

import requests
import base64
import json


# ============================================================================
# CONFIGURATION - UPDATE THESE VALUES
# ============================================================================

# M-Pesa Credentials (from Safaricom Developer Portal)
CONSUMER_KEY = "9mD1A3H1qw5grqdqkZ4X1G9zbNxioydHXL5An4nkUGRlNRKr"
CONSUMER_SECRET = "C2dqBSaGFUIporfYYuyhQgnfPEqLvCS3GvfAJ91ENkXI2bhqptlVXAqMelsEpLQR"

# Business Short Code (Paybill Number)
SHORT_CODE = "4159523"

# Callback URLs (must be publicly accessible HTTPS URLs)
VALIDATION_URL = "https://branchbusinessadvance.co.ke/payments/callback/validation/"
CONFIRMATION_URL = "https://branchbusinessadvance.co.ke/payments/callback/confirmation/"

# Response Type (what to do if validation fails)
# Options: "Completed" or "Cancelled"
RESPONSE_TYPE = "Completed"

# Environment
# Set to True for production, False for sandbox
IS_PRODUCTION = True

# ============================================================================


def get_access_token(consumer_key, consumer_secret, is_production):
    """
    Step 1: Generate M-Pesa access token
    
    API Endpoint:
    - Production: https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials
    - Sandbox: https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials
    """
    if is_production:
        url = "https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"
    else:
        url = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"
    
    # Create Basic Auth header
    credentials = f"{consumer_key}:{consumer_secret}"
    encoded_credentials = base64.b64encode(credentials.encode()).decode()
    
    headers = {
        "Authorization": f"Basic {encoded_credentials}",
        "Content-Type": "application/json"
    }
    
    print(f"\n{'='*70}")
    print("STEP 1: Generating Access Token")
    print(f"{'='*70}")
    print(f"URL: {url}")
    print(f"Consumer Key: {consumer_key[:10]}...")
    print(f"Authorization: Basic {encoded_credentials[:20]}...")
    
    try:
        response = requests.get(url, headers=headers, timeout=30)
        response.raise_for_status()
        
        data = response.json()
        access_token = data.get("access_token")
        
        if not access_token:
            raise Exception("No access token in response")
        
        print(f"\n✓ Success! Access Token: {access_token[:30]}...")
        return access_token
        
    except requests.exceptions.RequestException as e:
        print(f"\n✗ Error: {str(e)}")
        if hasattr(e.response, 'text'):
            print(f"Response: {e.response.text}")
        raise


def register_urls(access_token, short_code, validation_url, confirmation_url, 
                  response_type, is_production):
    """
    Step 2: Register callback URLs with M-Pesa
    
    API Endpoint:
    - Production: https://api.safaricom.co.ke/mpesa/c2b/v2/registerurl
    - Sandbox: https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl
    
    Note: Production uses v2, Sandbox uses v1
    """
    if is_production:
        url = "https://api.safaricom.co.ke/mpesa/c2b/v2/registerurl"
    else:
        url = "https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl"
    
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }
    
    payload = {
        "ShortCode": short_code,
        "ResponseType": response_type,
        "ConfirmationURL": confirmation_url,
        "ValidationURL": validation_url
    }
    
    print(f"\n{'='*70}")
    print("STEP 2: Registering Callback URLs")
    print(f"{'='*70}")
    print(f"URL: {url}")
    print(f"Short Code: {short_code}")
    print(f"Validation URL: {validation_url}")
    print(f"Confirmation URL: {confirmation_url}")
    print(f"Response Type: {response_type}")
    print(f"\nPayload:")
    print(json.dumps(payload, indent=2))
    
    try:
        response = requests.post(url, json=payload, headers=headers, timeout=30)
        response.raise_for_status()
        
        result = response.json()
        
        print(f"\n✓ Success! URLs Registered")
        print(f"\nResponse from M-Pesa:")
        print(json.dumps(result, indent=2))
        
        return result
        
    except requests.exceptions.RequestException as e:
        print(f"\n✗ Error: {str(e)}")
        if hasattr(e.response, 'text'):
            print(f"Response: {e.response.text}")
        raise


def main():
    """Main function to register M-Pesa URLs"""
    
    print("\n" + "="*70)
    print("M-PESA C2B URL REGISTRATION")
    print("="*70)
    
    # Validate configuration
    if CONSUMER_KEY == "YOUR_CONSUMER_KEY_HERE":
        print("\n✗ Error: Please update CONSUMER_KEY in the script")
        return
    
    if CONSUMER_SECRET == "YOUR_CONSUMER_SECRET_HERE":
        print("\n✗ Error: Please update CONSUMER_SECRET in the script")
        return
    
    if SHORT_CODE == "YOUR_SHORTCODE_HERE":
        print("\n✗ Error: Please update SHORT_CODE in the script")
        return
    
    # Display configuration
    print(f"\nEnvironment: {'PRODUCTION' if IS_PRODUCTION else 'SANDBOX'}")
    print(f"Short Code: {SHORT_CODE}")
    print(f"Validation URL: {VALIDATION_URL}")
    print(f"Confirmation URL: {CONFIRMATION_URL}")
    
    if IS_PRODUCTION:
        print("\n" + "!"*70)
        print("⚠️  WARNING: YOU ARE REGISTERING URLS IN PRODUCTION!")
        print("!"*70)
        # Skip confirmation prompt if running non-interactively
        import sys
        if sys.stdin.isatty():
            confirm = input("\nType 'yes' to continue: ")
            if confirm.lower() != 'yes':
                print("\nRegistration cancelled.")
                return
        else:
            print("\nRunning in non-interactive mode, proceeding automatically...")
            print("(Set IS_PRODUCTION = False to disable this)")
    
    try:
        # Step 1: Get access token
        access_token = get_access_token(CONSUMER_KEY, CONSUMER_SECRET, IS_PRODUCTION)
        
        # Step 2: Register URLs
        result = register_urls(
            access_token,
            SHORT_CODE,
            VALIDATION_URL,
            CONFIRMATION_URL,
            RESPONSE_TYPE,
            IS_PRODUCTION
        )
        
        # Success message
        print("\n" + "="*70)
        print("✓ URL REGISTRATION COMPLETED SUCCESSFULLY!")
        print("="*70)
        print("\nNext Steps:")
        print("1. Test the integration by making a payment to your shortcode")
        print("2. Monitor your callback endpoints for incoming requests")
        print("3. Check your application logs for any errors")
        print("\n")
        
    except Exception as e:
        print("\n" + "="*70)
        print("✗ URL REGISTRATION FAILED")
        print("="*70)
        print(f"\nError: {str(e)}")
        print("\nPlease check:")
        print("1. Your consumer key and secret are correct")
        print("2. Your shortcode is correct")
        print("3. Your callback URLs are publicly accessible (HTTPS)")
        print("4. You have internet connectivity")
        print("\n")


# ============================================================================
# POSTMAN INSTRUCTIONS
# ============================================================================
"""
To use this with Postman instead:

STEP 1: Generate Access Token
------------------------------
Method: GET
URL: https://api.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials

Headers:
    Authorization: Basic <base64_encoded_credentials>
    Content-Type: application/json

To create the Authorization header:
1. Combine your consumer key and secret: "consumer_key:consumer_secret"
2. Base64 encode the string
3. Add "Basic " prefix

Example in Python:
    import base64
    credentials = "your_key:your_secret"
    encoded = base64.b64encode(credentials.encode()).decode()
    print(f"Basic {encoded}")


STEP 2: Register URLs
---------------------
Method: POST
URL: https://api.safaricom.co.ke/mpesa/c2b/v2/registerurl

Headers:
    Authorization: Bearer <access_token_from_step_1>
    Content-Type: application/json

Body (raw JSON):
{
    "ShortCode": "YOUR_SHORTCODE",
    "ResponseType": "Completed",
    "ConfirmationURL": "https://branchbusinessadvance.co.ke/payments/callback/confirmation/",
    "ValidationURL": "https://branchbusinessadvance.co.ke/payments/callback/validation/"
}
"""


if __name__ == "__main__":
    main()
