#!/usr/bin/env python3
"""
HTTP Server for Games API with Admin Panel
Serves mock API responses for Unity client and a web UI for admin.
"""

import threading
from http.server import HTTPServer, BaseHTTPRequestHandler, ThreadingHTTPServer
import json
import uuid
import hmac
import hashlib
import urllib.parse

import urllib.request
import re

def scrape_playstore(package):
    url = f"https://play.google.com/store/apps/details?id={package}&hl=en"
    req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'})
    try:
        html = urllib.request.urlopen(req, timeout=10).read().decode('utf-8')
    except Exception as e:
        print(f"Scrape failed for {package}: {e}")
        return None
        
    data = {}
    
    # 1. Title
    title_match = re.search(r'<title[^>]*>(.*?) - Apps on Google Play</title>', html)
    if not title_match:
        title_match = re.search(r'<title[^>]*>(.*?)</title>', html)
    data['title'] = title_match.group(1).replace('&amp;', '&') if title_match else package
    
    # 2. Description
    desc = re.search(r'<meta itemprop="description" content="([^"]+)">', html)
    if not desc:
        desc = re.search(r'itemprop="description">([^<]+)', html)
    data['description'] = desc.group(1).replace('&quot;', '"') if desc else "Description not found."
    
    # 3. Category & Developer
    genre = re.search(r'itemprop="genre" href="/store/apps/category/[^"]+"><span[^>]*>(.*?)</span>', html)
    if not genre:
        genre = re.search(r'aria-label="([^"]+)"[^>]*href="/store/apps/category/', html)
    data['category'] = genre.group(1).replace('See more', '').strip() if genre else "App"
    
    dev = re.search(r'href="/store/apps/dev[^>]+><span[^>]*>(.*?)</span>', html)
    data['developer'] = dev.group(1) if dev else "Unknown"
    
    # 4. Rating & Installs
    rating = re.search(r'aria-label="Rated ([\d\.]+) stars', html)
    if not rating:
        rating = re.search(r'<div itemprop="starRating"[^>]*><meta itemprop="ratingValue" content="([^"]+)">', html)
    data['rating'] = rating.group(1) if rating else "0.0"
    
    installs = re.search(r'<div class="[^"]+">([\d\.,MK\+]+)\+?</div><span class="[^"]+">Downloads</span>', html)
    if not installs:
        installs = re.search(r'>([\d\.,MK\+]+)\+?</div><div[^>]*>Downloads</div>', html)
    data['installs'] = installs.group(1) + "+" if installs else "1K+"
    
    # 5. Media using exact dimensions
    matches = re.findall(r'\[(\d+),(\d+)\],\[null,null,"(https://play-lh\.googleusercontent\.com/[^"]+)"\]', html)
    
    icon_url = None
    banner_url = None
    screenshots = []
    
    for h, w, url in matches:
        h, w = int(h), int(w)
        if w == 512 and h == 512 and not icon_url:
            icon_url = url
        elif w == 1024 and h == 500 and not banner_url:
            banner_url = url
        elif (w > 512 or h > 512) and (w != 1024 or h != 500) and (w != 512 or h != 512) and w != h:
            # Must be a screenshot. Filter out squares.
            if url not in screenshots:
                screenshots.append(url)
    
    if not icon_url:
        icon_m = re.search(r'<meta property="og:image" content="(https://play-lh\.googleusercontent\.com/[^"]+)"', html)
        icon_url = icon_m.group(1) if icon_m else "https://ui-avatars.com/api/?name=App"
        
    data['icon'] = icon_url
    data['banner'] = banner_url if banner_url else icon_url
    data['screenshots'] = [s + "=w1000-h2000-rw" for s in screenshots[:6]]
    
    return data

import os
import uuid
import base64
import mimetypes

DB_FILE = 'database.json'
IMAGES_DIR = 'images'
ADMIN_PASSWORD = 'admin'
IMAGES_DIR = 'images'

# Ensure images directory exists
analytics_lock = threading.Lock()
if not os.path.exists(IMAGES_DIR):
    os.makedirs(IMAGES_DIR)

ANALYTICS_FILE = 'analytics.json'

def load_analytics():
    if not os.path.exists(ANALYTICS_FILE):
        return []
    with open(ANALYTICS_FILE, 'r') as f:
        try:
            return json.load(f)
        except Exception:
            return []

def scrape_appstore(package):
    import json
    import urllib.request
    url = f"https://itunes.apple.com/lookup?bundleId={package}"
    req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
    try:
        response = urllib.request.urlopen(req, timeout=10).read().decode("utf-8")
        data = json.loads(response)
    except Exception as e:
        print(f"Scrape failed for {package}: {e}")
        return None
        
    if data.get("resultCount", 0) == 0:
        return None
        
    result = data["results"][0]
    
    return {
        "title": result.get("trackName", package),
        "description": result.get("description", "Description not found."),
        "category": result.get("primaryGenreName", "App"),
        "developer": result.get("artistName", "Unknown"),
        "rating": str(round(result.get("averageUserRating", 0.0), 1)) if result.get("averageUserRating") else "0.0",
        "installs": "N/A",
        "icon": result.get("artworkUrl512", f"https://ui-avatars.com/api/?name={package[:2].upper()}&background=F3E8FF&color=9333EA"),
        "banner": result.get("screenshotUrls", [""])[0] if result.get("screenshotUrls") else "",
        "screenshots": result.get("screenshotUrls", [])[:4]
    }

def save_analytics(data):
    with open(ANALYTICS_FILE, 'w') as f:
        json.dump(data, f, indent=4)

def load_db():
    if not os.path.exists(DB_FILE):
        default_data = {
            "apps": {
                "default": {
                    "games": [
                        {
                            "id": str(uuid.uuid4()),
                            "title": "Magic Boca",
                            "description": "Fun game",
                            "icon": "https://via.placeholder.com/150/FF6B6B/FFFFFF?text=Magic+Boca",
                            "android": "https://play.google.com/store/apps/details?id=com.example.magicboca",
                            "ios": "",
                            "placement": "custom_level_end",
                            "order": 1
                        }
                    ],
                    "daily_rewards": [50, 100, 150, 200, 250, 300, 500]
                }
            }
        }
        save_db(default_data)
        return default_data
    
    with open(DB_FILE, 'r') as f:
        data = json.load(f)
        
    # Migrate old data format if needed
    if "apps" not in data:
        old_games = data.get("games", [])
        old_rewards = data.get("daily_rewards", [])
        data = {
            "apps": {
                "default": {
                    "games": old_games,
                    "daily_rewards": old_rewards
                }
            }
        }
        save_db(data)
        
    if "global_promo_games" not in data:
        # Move games from 'default' to global if it's the first time
        data["global_promo_games"] = data["apps"].get("default", {}).get("games", [])
        save_db(data)
        

    # Ensure all games have IDs
    modified = False
    for app_id, app_data in data["apps"].items():
        if "secret_key" not in app_data:
            app_data["secret_key"] = uuid.uuid4().hex
            modified = True
        if "notifications" not in app_data:
            app_data["notifications"] = []
            modified = True
        if "assigned_promos" not in app_data:

            app_data["assigned_promos"] = []
            modified = True
            
        for game in app_data.get('games', []):
            if 'id' not in game:
                game['id'] = str(uuid.uuid4())
                modified = True
            
    if modified:
        save_db(data)
        
    return data

def save_db(data):
    with open(DB_FILE, 'w') as f:
        json.dump(data, f, indent=2)


def get_country_from_ip(ip):
    if ip == '127.0.0.1' or ip == '::1':
        return 'Localhost'
    try:
        url = f"http://ip-api.com/json/{ip}?fields=country"
        req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
        with urllib.request.urlopen(req, timeout=2) as response:
            data = json.loads(response.read().decode())
            return data.get('country', 'Unknown')
    except Exception as e:
        print(f"IP Geo Error: {e}")
        return 'Unknown'

class GamesAPIHandler(BaseHTTPRequestHandler):
    
    def set_cors_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE, PUT')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type, Accept, Accept-Language, X-GAME-ID, X-API-KEY, X-ADMIN-PASSWORD')
        self.end_headers()
        
    def do_OPTIONS(self):
        self.send_response(200)
        self.set_cors_headers()
        
    def send_json(self, status_code, data):
        body = json.dumps(data, indent=2).encode('utf-8')
        self.send_response(status_code)
        self.send_header('Content-type', 'application/json')
        self.send_header('Content-Length', str(len(body)))
        self.set_cors_headers()
        self.wfile.write(body)
        
    def check_auth(self):
        # We only protect /api/admin/ routes (except login)
        if self.path.startswith('/api/admin/') and self.path != '/api/admin/login':
            if self.headers.get('X-ADMIN-PASSWORD') != ADMIN_PASSWORD:
                self.send_json(401, {"error": "Unauthorized. Invalid password."})
                return False
        return True

    def do_GET(self):
        with open("server_requests.log", "a") as f: f.write(f"GET {self.path}\n")
        if not self.check_auth():
            return
        
        parsed_path = urllib.parse.urlparse(self.path)
        path = urllib.parse.unquote(parsed_path.path)
        
        query = urllib.parse.parse_qs(parsed_path.query)
        package = query.get('package', ['default'])[0]
        print(f"Parsed path: {path}, package: {package}")

        if path == '/':
            status = {
                "status": "online",
                "message": "Games API Server is running (Multi-Tenant)!",
                "endpoints": [
                    "GET /admin",
                    "GET /api/games?package=...",
                    "GET /images/..."
                ]
            }
            self.send_json(200, status)
            
        elif path == '/admin':
            if os.path.exists('admin.html'):
                with open('admin.html', 'rb') as f:
                    body = f.read()
                self.send_response(200)
                self.send_header('Content-type', 'text/html')
                self.send_header('Content-Length', str(len(body)))
                self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
                self.end_headers()
                self.wfile.write(body)
            else:
                self.send_json(404, {"error": "admin.html not found"})
                
        elif path.startswith('/images/'):
            filename = os.path.basename(path)
            filepath = os.path.join(IMAGES_DIR, filename)
            if os.path.exists(filepath):
                self.send_response(200)
                mtype, _ = mimetypes.guess_type(filepath)
                self.send_header('Content-type', mtype or 'application/octet-stream')
                self.end_headers()
                with open(filepath, 'rb') as f:
                    self.wfile.write(f.read())
            else:
                self.send_response(404)
                self.end_headers()
                self.wfile.write(b"Image not found")

        elif path == '/api/admin/playstore':
            package = query.get('package', [None])[0]
            if not package:
                self.send_json(400, {"error": "Missing package"})
                return
                
            db = load_db()
            app_cache = db.get("playstore_cache", {})
            
            # Check cache first
            if package in app_cache:
                print(f"Returning cached playstore data for {package}")
                self.send_json(200, app_cache[package])
                return
                
            platform = db["apps"].get(package, {}).get("platform", "android")
            
            # Scrape live
            print(f"Scraping store for {package} (platform: {platform})...")
            if platform == "ios":
                scraped_data = scrape_appstore(package)
            else:
                scraped_data = scrape_playstore(package)
            
            if scraped_data:
                if "playstore_cache" not in db:
                    db["playstore_cache"] = {}
                db["playstore_cache"][package] = scraped_data
                save_db(db)
                self.send_json(200, scraped_data)
            else:
                self.send_json(404, {"error": "App not found or scrape failed"})

        elif path == '/api/admin/apps':
            print("Handling /api/admin/apps")
            db = load_db()
            print("DB loaded")
            self.send_json(200, list(db["apps"].keys()))
            print("Response sent")
                
        elif path == '/api/admin/games':
            db = load_db()
            app_data = db["apps"].get(package, {})
            self.send_json(200, app_data.get('games', []))
            
        elif path == '/api/games':
            db = load_db()
            app_data = db["apps"].get(package, {})
            assigned = app_data.get("assigned_promos", [])
            global_games = db.get("global_promo_games", [])
            app_specific_games = app_data.get("games", [])
            
            active_games = []
            
            def prep_game(g, p=None):
                g_c = dict(g)
                if p is not None: g_c["placement"] = str(p)
                g_c["active"] = g_c.get("is_active", True)
                g_c["description"] = g_c.get("description", "")
                
                # Parental gate aliases
                is_pg = g_c.get("parental_gate", False)
                g_c["require_parent"] = is_pg
                g_c["requireParent"] = is_pg
                g_c["parentalGate"] = is_pg
                g_c["is_parent"] = is_pg
                
                if "placement" in g_c: g_c["placement"] = str(g_c["placement"])
                return g_c
            
            # Add app-specific custom cross promos
            for game in app_specific_games:
                if game.get("is_active", True):
                    active_games.append(prep_game(game))
                    
            if len(assigned) > 0 and isinstance(assigned[0], dict):
                for a in assigned:
                    promo_id = a.get("id")
                    placement = a.get("placement", "1")
                    for g in global_games:
                        if g.get("id") == promo_id and g.get("is_active", True):
                            active_games.append(prep_game(g, placement))
                            break
            else:
                for promo_id in assigned:
                    for g in global_games:
                        if g.get("id") == promo_id and g.get("is_active", True):
                            active_games.append(prep_game(g))
                            break
                            
            self.send_json(200, active_games)
            
        elif path == '/api/daily_rewards':
            db = load_db()
            app_data = db["apps"].get(package, {})
            self.send_json(200, app_data.get('daily_rewards', [50, 100, 150, 200, 250, 300, 500]))
            
        elif path == '/api/config':
            db = load_db()
            app_data = db["apps"].get(package, {})
            assigned = app_data.get("assigned_promos", [])
            global_games = db.get("global_promo_games", [])
            app_specific_games = app_data.get("games", [])
            
            active_games = []
            def prep_game(g, p=None):
                g_c = dict(g)
                if p is not None: g_c["placement"] = str(p)
                g_c["active"] = g_c.get("is_active", True)
                g_c["description"] = g_c.get("description", "")
                
                # Parental gate aliases
                is_pg = g_c.get("parental_gate", False)
                g_c["require_parent"] = is_pg
                g_c["requireParent"] = is_pg
                g_c["parentalGate"] = is_pg
                g_c["is_parent"] = is_pg
                
                if "placement" in g_c: g_c["placement"] = str(g_c["placement"])
                return g_c
                
            for game in app_specific_games:
                if game.get("is_active", True):
                    active_games.append(prep_game(game))
                    
            if len(assigned) > 0 and isinstance(assigned[0], dict):
                for a in assigned:
                    promo_id = a.get("id")
                    placement = a.get("placement", "1")
                    for g in global_games:
                        if g.get("id") == promo_id and g.get("is_active", True):
                            active_games.append(prep_game(g, placement))
                            break
            else:
                for promo_id in assigned:
                    for g in global_games:
                        if g.get("id") == promo_id and g.get("is_active", True):
                            active_games.append(prep_game(g))
                            break

            config = {
                "gameKey": package,
                "moreGames": {
                    "enabled": True,
                    "list": active_games
                }
            }
            self.send_json(200, config)
            
        elif path == '/api/admin/analytics':
            analytics_data = load_analytics()
            # Filter analytics by package
            filtered_data = [ev for ev in analytics_data if ev.get('package_name', 'default') == package]
            
            start_date = query.get('start_date', [None])[0]
            if start_date:
                # Filter events that occurred on or after start_date
                filtered_data = [ev for ev in filtered_data if ev.get('timestamp', '')[:10] >= start_date]
                
            self.send_json(200, filtered_data)

        elif path == '/api/admin/global_analytics':
            analytics_data = load_analytics()
            self.send_json(200, analytics_data)
            
        elif path == '/api/admin/funnels':
            analytics_data = load_analytics()
            filtered = [ev for ev in analytics_data if ev.get('package_name', 'default') == package]
            
            # Aggregate funnels
            funnel_data = {}
            for ev in filtered:
                t = ev.get('type')
                if t and t.startswith('funnel_'):
                    # e.g., funnel_1_LevelStart
                    funnel_data[t] = funnel_data.get(t, 0) + 1
            self.send_json(200, funnel_data)

        elif path == '/api/admin/notifications':
            db = load_db()
            app_data = db["apps"].get(package, {})
            self.send_json(200, app_data.get("notifications", []))
            
        elif path == '/api/admin/secret_key':
            db = load_db()
            app_data = db["apps"].get(package, {})
            self.send_json(200, {"secret_key": app_data.get("secret_key", "")})
            
        elif path == '/api/notifications':
            # Used by Unity SDK to fetch active in-game notifications
            db = load_db()
            app_data = db["apps"].get(package, {})
            active_notifs = [n for n in app_data.get("notifications", []) if n.get("is_active", True)]
            # We just return the latest active one to show a popup
            self.send_json(200, active_notifs[0] if active_notifs else {})

        elif path == '/api/admin/global_games':
            db = load_db()
            self.send_json(200, db.get("global_promo_games", []))
            
        elif path == '/api/admin/app_promos':
            db = load_db()
            app_data = db["apps"].get(package, {})
            self.send_json(200, app_data.get("assigned_promos", []))
            
        else:
            self.send_json(404, {"error": "Not Found"})


    def do_DELETE(self):
        if not self.check_auth():
            return
            
        parsed_path = urllib.parse.urlparse(self.path)
        path = parsed_path.path
        query = urllib.parse.parse_qs(parsed_path.query)
        package = query.get('package', [None])[0]
        
        if path == '/api/admin/apps':
            if package:
                db = load_db()
                if package in db["apps"]:
                    del db["apps"][package]
                    save_db(db)
                    self.send_json(200, {"success": True})
                else:
                    self.send_json(404, {"error": "Package not found"})
            else:
                self.send_json(400, {"error": "Missing package parameter"})
        else:
            self.send_json(404, {"error": "Not Found"})

    def do_POST(self):
        if not self.check_auth():
            return
            
        parsed_path = urllib.parse.urlparse(self.path)
        path = parsed_path.path
        
        query = urllib.parse.parse_qs(parsed_path.query)
        package = query.get('package', ['default'])[0]
        
        content_length = int(self.headers.get('Content-Length', 0))
        post_data = self.rfile.read(content_length) if content_length > 0 else b"{}"
        
        try:
            req_json = json.loads(post_data.decode('utf-8'))
        except json.JSONDecodeError:
            req_json = {}
            
        if path == '/api/admin/login':
            password = req_json.get("password", "")
            if password == ADMIN_PASSWORD:
                self.send_json(200, {"success": True})
            else:
                self.send_json(401, {"error": "Invalid password"})
                
        elif path == '/api/admin/playstore':
            package = query.get('package', [None])[0]
            if not package:
                self.send_json(400, {"error": "Missing package"})
                return
                
            db = load_db()
            app_cache = db.get("playstore_cache", {})
            
            # Check cache first
            if package in app_cache:
                print(f"Returning cached playstore data for {package}")
                self.send_json(200, app_cache[package])
                return
                
            platform = db["apps"].get(package, {}).get("platform", "android")
            
            # Scrape live
            print(f"Scraping store for {package} (platform: {platform})...")
            if platform == "ios":
                scraped_data = scrape_appstore(package)
            else:
                scraped_data = scrape_playstore(package)
            
            if scraped_data:
                if "playstore_cache" not in db:
                    db["playstore_cache"] = {}
                db["playstore_cache"][package] = scraped_data
                save_db(db)
                self.send_json(200, scraped_data)
            else:
                self.send_json(404, {"error": "App not found or scrape failed"})

        elif path == '/api/admin/apps':
            new_package = req_json.get("package")
            platform = req_json.get("platform", "android")
            if new_package:
                db = load_db()
                if new_package not in db["apps"]:
                    db["apps"][new_package] = {"platform": platform, "games": [], "daily_rewards": [50, 100, 150, 200, 250, 300, 500]}
                    save_db(db)
                self.send_json(200, {"success": True})
            else:
                self.send_json(400, {"error": "Missing package"})
            
        elif path == '/api/admin/games':
            db = load_db()
            if package not in db["apps"]:
                db["apps"][package] = {}
            # Ensure any new games have IDs
            for game in req_json:
                if 'id' not in game or not game['id']:
                    game['id'] = str(uuid.uuid4())
                    
            db["apps"][package]['games'] = req_json
            save_db(db)
            self.send_json(200, {"success": True})
            
        elif path == '/api/admin/daily_rewards':
            db = load_db()
            if package not in db["apps"]:
                db["apps"][package] = {}
            db["apps"][package]['daily_rewards'] = req_json
            save_db(db)
            self.send_json(200, {"success": True})
            
        elif path == '/api/admin/notifications':
            db = load_db()
            if package not in db["apps"]:
                db["apps"][package] = {}
            for n in req_json:
                if 'id' not in n or not n['id']:
                    n['id'] = str(uuid.uuid4())
            db["apps"][package]['notifications'] = req_json
            save_db(db)
            self.send_json(200, {"success": True})

        elif path == '/api/admin/global_games':
            db = load_db()
            for game in req_json:
                if 'id' not in game or not game['id']:
                    game['id'] = str(uuid.uuid4())
            db["global_promo_games"] = req_json
            save_db(db)
            self.send_json(200, {"success": True})
            
        elif path == '/api/admin/app_promos':
            db = load_db()
            if package not in db["apps"]:
                db["apps"][package] = {"games": [], "daily_rewards": [50, 100, 150, 200, 250, 300, 500], "assigned_promos": []}
            
            db["apps"][package]["assigned_promos"] = req_json.get("assigned_promos", [])
            save_db(db)
            self.send_json(200, {"success": True})
            
        elif path == '/api/admin/upload':
            try:
                b64_data = req_json.get('base64_data', '')
                filename = req_json.get('filename', 'image.png')
                
                if ',' in b64_data:
                    b64_data = b64_data.split(',')[1]
                    
                image_data = base64.b64decode(b64_data)
                
                # Generate unique filename
                ext = os.path.splitext(filename)[1] or '.png'
                safe_filename = os.path.basename(filename).replace(' ', '_')
                unique_filename = f"{uuid.uuid4().hex[:8]}_{safe_filename}"
                filepath = os.path.join(IMAGES_DIR, unique_filename)
                
                with open(filepath, 'wb') as f:
                    f.write(image_data)
                    
                url = f"http://localhost:8001/images/{urllib.parse.quote(unique_filename)}"
                self.send_json(200, {"success": True, "url": url})
            except Exception as e:
                self.send_json(500, {"success": False, "error": str(e)})
                
        elif path == '/api/analytics':
            # Receive bulk analytics events from client
            try:
                global_package = req_json.get('package_name', 'default')
                
                # --- Security Check ---
                db = load_db()
                app_data = db["apps"].get(global_package, {})
                secret_key = app_data.get("secret_key", "")
                
                # If secret key exists, check signature
                if secret_key:
                    signature = self.headers.get('X-Signature', '')
                    payload_str = post_data.decode('utf-8')
                    expected = hmac.new(secret_key.encode('utf-8'), payload_str.encode('utf-8'), hashlib.sha256).hexdigest()
                    if not hmac.compare_digest(expected, signature):
                        print(f"⚠️ Warning: Invalid signature for {global_package}. Accepting anyway for local testing.")
                
                events = req_json.get('events', [])
                if events:
                    client_ip = self.headers.get('X-Forwarded-For', self.client_address[0]).split(',')[0].strip()
                    
                    with analytics_lock:
                        analytics_data = load_analytics()
                        for ev in events:
                            # Ensure every event has a package_name
                            if 'package_name' not in ev:
                                ev['package_name'] = global_package
                                
                            # If first_open or session_start, fetch country
                            if ev.get('type') in ['first_open', 'session_start']:
                                ev['country'] = get_country_from_ip(client_ip)

                        analytics_data.extend(events)
                        save_analytics(analytics_data)
                self.send_json(200, {"success": True, "count": len(events)})
            except Exception as e:
                self.send_json(500, {"success": False, "error": str(e)})
            
        else:
            self.send_json(404, {"error": "Not Found"})

    def log_message(self, format, *args):
        return

    def address_string(self):
        # Prevent reverse DNS lookup delays
        return str(self.client_address[0])

import threading

def run_server(port=8001, test_mode=False):
    server_address = ('', port)
    httpd = ThreadingHTTPServer(server_address, GamesAPIHandler)
    
    if test_mode:
        httpd.timeout = 0.5
        t = threading.Thread(target=httpd.serve_forever, daemon=True)
        t.start()
        print(f"🧪 Test server started on :{port}")
        return httpd
    
    print("=" * 60)
    print("🎮 Games Mock API Server Started!")
    print("=" * 60)
    print(f"📡 Listening on: http://localhost:{port}")
    print(f"🔑 Admin Panel: http://localhost:{port}/admin")
    print("=" * 60)
    
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n\n🛑 Server stopped")
        httpd.server_close()

if __name__ == '__main__':
    run_server()
