import socket
import requests
import threading
import time
from urllib.parse import urlparse
import subprocess
import sys
import json
import os

class VertexTunnel:
    def __init__(self, script_path, custom_domain=None, port=5552):
        self.script_path = script_path
        self.custom_domain = custom_domain
        self.port = port
        self.public_url = None
        self.proc = None
        self.tunnel_thread = None
        
    def is_port_available(self, port):
        """Check if port is available"""
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            return s.connect_ex(('localhost', port)) != 0
    
    def modify_flask_app(self):
        """Modify Flask app to run on correct host and port"""
        with open(self.script_path, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # Replace app.run() parameters
        if 'app.run(' in content:
            new_run_line = f"app.run(host='0.0.0.0', port={self.port}, debug=False)"
            content = content.replace(
                "app.run(host='0.0.0.0', port=5552)",
                new_run_line
            )
            content = content.replace(
                "app.run(host=\"0.0.0.0\", port=5552)",
                new_run_line
            )
            content = content.replace(
                "app.run()",
                new_run_line
            )
        
        # Create temporary file
        temp_file = f"{self.script_path}.tmp.py"
        with open(temp_file, 'w', encoding='utf-8') as f:
            f.write(content)
        
        return temp_file
    
    def start_tunnel(self):
        """Start ngrok-like tunneling service"""
        try:
            # Try using localtunnel or ngrok
            self.public_url = self.start_localtunnel()
            if self.public_url:
                print(f"✅ Tunnel created successfully!")
                print(f"🌐 Public URL: {self.public_url}")
                print(f"🔗 Local URL: http://localhost:{self.port}")
                return self.public_url
        except Exception as e:
            print(f"⚠️  Tunnel error: {e}")
        
        return None
    
    def start_localtunnel(self):
        """Use localtunnel service"""
        try:
            # You can use various free tunneling services
            # Option 1: localtunnel
            import localtunnel
            lt = localtunnel.Localtunnel(self.port, subdomain=self.custom_domain)
            url = lt.start()
            return url
        except:
            # Option 2: Use ssh tunneling (fallback)
            return self.create_ssh_tunnel()
    
    def create_ssh_tunnel(self):
        """Create SSH tunnel as fallback"""
        try:
            # This requires SSH access to a public server
            # You can implement your own tunnel server logic here
            print("🔧 Using custom tunnel server...")
            
            # Example with a mock tunnel service
            response = requests.post(
                'https://tunnel.vertexweb.dev/create',
                json={
                    'port': self.port,
                    'domain': self.custom_domain
                }
            )
            
            if response.status_code == 200:
                return response.json()['url']
        except:
            pass
        
        return None
    
    def run_script(self):
        """Run the Python script"""
        temp_file = self.modify_flask_app()
        
        # Run the script
        self.proc = subprocess.Popen(
            [sys.executable, temp_file],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        
        # Wait for server to start
        time.sleep(3)
        
        # Clean up temp file
        os.remove(temp_file)
        
        # Print output
        def read_output():
            while True:
                output = self.proc.stdout.readline()
                if output:
                    print(f"[APP]: {output.strip()}")
                if self.proc.poll() is not None:
                    break
        
        threading.Thread(target=read_output, daemon=True).start()
    
    def start(self):
        """Start everything"""
        print(f"🚀 Starting Vertex Web Tunnel...")
        print(f"📁 Script: {self.script_path}")
        
        if not self.is_port_available(self.port):
            print(f"❌ Port {self.port} is already in use!")
            return False
        
        # Start Flask app
        self.run_script()
        
        # Start tunnel
        self.public_url = self.start_tunnel()
        
        if self.public_url:
            print("\n" + "="*50)
            print(f"✅ SUCCESS! Your app is now public!")
            print(f"🌍 Public URL: {self.public_url}")
            print(f"📊 API Endpoint: {self.public_url}/accinfo")
            print("="*50 + "\n")
            
            # Keep script running
            try:
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                print("\n🔴 Shutting down...")
                if self.proc:
                    self.proc.terminate()
            
            return True
        
        return False

def create_tunnel(script_path, domain=None, port=5552):
    """Main function to create tunnel"""
    tunnel = VertexTunnel(script_path, domain, port)
    return tunnel.start()