#!/usr/bin/env python3
"""
Backdrops Database Injector
Directly manipulates the SQLite premium database

Requirements: rooted device or adb with appropriate permissions
"""

import subprocess
import sys
import os

PACKAGE = "com.backdrops.wallpapers"
DB_PATH = f"/data/data/{PACKAGE}/databases/premium"
LOCAL_DB = "premium_modified.db"

PREMIUM_SKUS = [
    "premium.pack.trinity",
    "premium.pack.amoled", 
    "premium.pro",
    "premium.pack.acid",
    "premium.pack.optic",
    "premium.pack.void",
    "premium.pack.synth"
]

def run_cmd(cmd):
    """Run shell command and return output"""
    try:
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
        return result.returncode == 0, result.stdout, result.stderr
    except Exception as e:
        return False, "", str(e)

def check_adb():
    """Check if adb is available"""
    success, _, _ = run_cmd("adb version")
    return success

def check_device():
    """Check if device is connected"""
    success, output, _ = run_cmd("adb devices")
    if not success:
        return False
    lines = output.strip().split('\n')
    return len(lines) > 1 and 'device' in lines[1]

def stop_app():
    """Stop the Backdrops app"""
    print("[*] Stopping app...")
    run_cmd(f"adb shell am force-stop {PACKAGE}")
    return True

def pull_database():
    """Pull database from device"""
    print(f"[*] Pulling database from device...")
    success, _, error = run_cmd(f"adb pull {DB_PATH} {LOCAL_DB}")
    if not success:
        print(f"[!] Failed to pull database: {error}")
        print("[!] Note: You may need root access or run-as permissions")
        return False
    
    if os.path.exists(LOCAL_DB):
        print(f"[+] Database pulled successfully: {LOCAL_DB}")
        return True
    return False

def inject_purchases():
    """Inject premium purchases into database"""
    print("[*] Injecting premium purchases...")
    
    if not os.path.exists(LOCAL_DB):
        print("[!] Database file not found!")
        return False
    
    # Create SQL commands
    sql_commands = []
    for idx, sku in enumerate(PREMIUM_SKUS, start=1):
        token = f"frida_injected_token_{sku}"
        sql = f"INSERT OR REPLACE INTO Premium (id, item, token) VALUES ({idx}, '{sku}', '{token}');"
        sql_commands.append(sql)
    
    # Write to temp SQL file
    sql_file = "inject.sql"
    with open(sql_file, 'w') as f:
        f.write('\n'.join(sql_commands))
    
    # Execute SQL
    success, output, error = run_cmd(f'sqlite3 {LOCAL_DB} < {sql_file}')
    
    # Cleanup
    if os.path.exists(sql_file):
        os.remove(sql_file)
    
    if not success:
        print(f"[!] SQL injection failed: {error}")
        return False
    
    print("[+] Injected purchases:")
    for sku in PREMIUM_SKUS:
        print(f"    ✓ {sku}")
    
    return True

def verify_database():
    """Verify database contents"""
    print("\n[*] Verifying database contents...")
    success, output, _ = run_cmd(f"sqlite3 {LOCAL_DB} 'SELECT * FROM Premium'")
    
    if success and output:
        print("[+] Database contents:")
        print(output)
        return True
    else:
        print("[!] Could not verify database")
        return False

def push_database():
    """Push modified database back to device"""
    print("\n[*] Pushing modified database to device...")
    
    # First, try to backup original
    run_cmd(f"adb shell cp {DB_PATH} {DB_PATH}.backup")
    
    # Push modified database
    success, _, error = run_cmd(f"adb push {LOCAL_DB} {DB_PATH}")
    
    if not success:
        print(f"[!] Failed to push database: {error}")
        print("[!] You may need root access")
        return False
    
    # Set permissions
    run_cmd(f"adb shell chmod 660 {DB_PATH}")
    run_cmd(f"adb shell chown u0_a$(adb shell stat -c '%u' {DB_PATH} | cut -d '_' -f 3):u0_a$(adb shell stat -c '%u' {DB_PATH} | cut -d '_' -f 3) {DB_PATH}")
    
    print("[+] Database pushed successfully!")
    return True

def start_app():
    """Start the app"""
    print("\n[*] Starting app...")
    run_cmd(f"adb shell monkey -p {PACKAGE} 1")
    print("[+] App started!")

def main():
    print("=" * 70)
    print("  Backdrops Database Injector")
    print("  Direct SQLite Database Manipulation")
    print("=" * 70)
    print()
    
    # Check requirements
    if not check_adb():
        print("[!] Error: adb not found in PATH")
        print("[!] Install Android SDK Platform Tools")
        sys.exit(1)
    
    if not check_device():
        print("[!] Error: No device connected")
        print("[!] Connect your Android device via USB")
        print("[!] Make sure USB debugging is enabled")
        sys.exit(1)
    
    print("[+] ADB ready")
    print("[+] Device connected")
    print()
    
    # Warning
    print("⚠️  WARNING ⚠️")
    print("This tool directly modifies the app's database.")
    print("- Requires root access or run-as permissions")
    print("- May cause app instability")
    print("- Backup will be created automatically")
    print()
    
    # Auto-continue for automation
    print("[*] Auto-continuing...")
    # response = input("Continue? (yes/no): ").strip().lower()
    # if response != 'yes':
    #     print("[*] Aborted by user")
    #     sys.exit(0)
    
    print()
    
    # Execute injection workflow
    try:
        # Stop app
        if not stop_app():
            print("[!] Could not stop app")
            sys.exit(1)
        
        # Pull database
        if not pull_database():
            print("\n[!] Could not pull database from device")
            print("\n[*] Alternative: Use Frida runtime injection instead!")
            print("    Run: python backdoors_controller.py")
            sys.exit(1)
        
        # Inject purchases
        if not inject_purchases():
            sys.exit(1)
        
        # Verify
        verify_database()
        
        # Push back
        if not push_database():
            print("\n[!] Could not push database to device")
            print("[*] But you can inspect the local database:")
            print(f"    sqlite3 {LOCAL_DB}")
            sys.exit(1)
        
        # Start app
        start_app()
        
        print("\n" + "=" * 70)
        print("  ✅ SUCCESS!")
        print("=" * 70)
        print("  All premium packs have been injected into the database!")
        print("  Open the app and check premium collections.")
        print("=" * 70)
        
        # Cleanup option
        print()
        cleanup = input("Remove local database file? (y/n): ").strip().lower()
        if cleanup == 'y':
            if os.path.exists(LOCAL_DB):
                os.remove(LOCAL_DB)
                print(f"[+] Removed {LOCAL_DB}")
        else:
            print(f"[*] Local database kept: {LOCAL_DB}")
            print(f"    Inspect with: sqlite3 {LOCAL_DB}")
        
    except KeyboardInterrupt:
        print("\n\n[*] Interrupted by user")
        sys.exit(1)
    except Exception as e:
        print(f"\n[!] Error: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)

if __name__ == "__main__":
    main()
