import json
import time
import os
from playwright.sync_api import sync_playwright

class SnapchatWebClient:
    def __init__(self, session_dir="./snapchat_session", headless=False):
        self.session_dir = session_dir
        self.headless = headless

    def get_messages(self):
        messages_data = []
        
        with sync_playwright() as p:
            print(f"Launching browser... (Headless: {self.headless})")
            browser = p.chromium.launch_persistent_context(
                user_data_dir=self.session_dir,
                headless=self.headless,
                viewport={"width": 1280, "height": 720},
                args=["--disable-blink-features=AutomationControlled"]
            )
            
            page = browser.pages[0] if browser.pages else browser.new_page()
            
            # --- REVERSE ENGINEERING HOOKS ---
            # We will intercept all network traffic to find the GraphQL/gRPC calls for messages
            print("Setting up network interception...")
            
            def handle_response(response):
                url = response.url
                # We log interesting endpoints to reverse engineer the payload
                if any(x in url for x in ["messaging", "chat", "conversations", "media", "webclient"]):
                    try:
                        content_type = response.headers.get("content-type", "")
                        if "application/json" in content_type:
                            print(f"\n[INTERCEPTED HTTP API]: {url}")
                            body = response.json()
                            safe_name = url.split("?")[0].split("/")[-1].replace(".json", "")
                            filename = f"intercept_http_{safe_name}_{int(time.time())}.json"
                            with open(filename, "w") as f:
                                json.dump(body, f, indent=2)
                            print(f"  -> Payload saved to {filename}")
                        elif "application/grpc" in content_type or "application/x-protobuf" in content_type:
                            print(f"\n[INTERCEPTED GRPC API]: {url}")
                            try:
                                body = response.body()
                                safe_name = url.split("?")[0].split("/")[-1]
                                filename = f"intercept_grpc_{safe_name}_{int(time.time()*1000)}.bin"
                                with open(filename, "wb") as f:
                                    f.write(body)
                                print(f"  -> Binary payload saved to {filename} ({len(body)} bytes)")
                            except Exception as e:
                                print(f"  -> Could not read body: {e}")
                    except Exception as e:
                        pass

            def handle_websocket(web_socket):
                print(f"\n[WEBSOCKET OPENED]: {web_socket.url}")
                
                def on_frames_received(payload):
                    # Payload is either bytes or str
                    is_binary = isinstance(payload, bytes)
                    print(f"  -> WS Received: {'Binary' if is_binary else 'Text'} ({len(payload)} bytes)")
                    # Save the payload
                    filename = f"intercept_ws_{int(time.time() * 1000)}.{'bin' if is_binary else 'txt'}"
                    with open(filename, "wb" if is_binary else "w") as f:
                        f.write(payload)
                
                web_socket.on("framereceived", on_frames_received)

            page.on("response", handle_response)
            page.on("websocket", handle_websocket)
            # ---------------------------------
            
            page.goto("https://web.snapchat.com/")
            
            print("Please log in manually if you haven't already.")
            print("Once logged in, click on different conversations to capture the message payloads.")
            print("The script is now listening to the Snapchat API... (Press Ctrl+C in terminal to stop)")
            
            try:
                # Keep the browser open indefinitely and extract decrypted DOM messages periodically
                print("\n[DOM EXTRACTOR] Démarrage de la lecture en clair depuis l'interface...")
                last_msg_count = 0
                
                while True:
                    # Javascript to extract messages from the screen
                    js_code = """
                    () => {
                        let messages = [];
                        // Find all list items
                        let items = document.querySelectorAll('li');
                        
                        items.forEach(item => {
                            let text = item.innerText.trim();
                            let media = [];
                            
                            // Cherche les images, vidéos et audios (souvent des liens blob: decrytpés)
                            item.querySelectorAll('img, video, audio').forEach(el => {
                                if(el.src && !el.src.includes('avatar') && !el.src.includes('bitmoji')) {
                                    media.push(el.src);
                                }
                            });
                            
                            if(text.length > 0 || media.length > 0) {
                                messages.push({
                                    text: text,
                                    media: media
                                });
                            }
                        });
                        
                        // Deduplicate simple
                        return Array.from(new Set(messages.map(JSON.stringify))).map(JSON.parse);
                    }
                    """
                    
                    try:
                        extracted_messages = page.evaluate(js_code)
                        if len(extracted_messages) != last_msg_count and len(extracted_messages) > 0:
                            last_msg_count = len(extracted_messages)
                            print(f"[DOM] {last_msg_count} messages/médias trouvés à l'écran. Sauvegarde en cours...")
                            with open("decrypted_messages.json", "w", encoding="utf-8") as f:
                                json.dump(extracted_messages, f, indent=2, ensure_ascii=False)
                    except Exception as e:
                        pass # Ignore evaluation errors when navigating
                    
                    time.sleep(5)
                    
            except KeyboardInterrupt:
                print("Stopping reverse engineering listener...")
                
            browser.close()
            
        return messages_data

if __name__ == "__main__":
    client = SnapchatWebClient(headless=False)
    client.get_messages()
