import asyncio
import os
import json
from aiohttp import web
from app.services import locket, nextdns
from app.config import NEXTDNS_KEY, TOKEN_MANAGER, USE_DATABASE_TOKENS

# Simple rate limiter
active_requests = set()

async def serve_index(request):
    filepath = os.path.join(os.path.dirname(__file__), "static", "index.html")
    return web.FileResponse(filepath)

async def api_resolve(request):
    data = await request.json()
    username = data.get("username", "").strip()
    
    if not username:
        return web.json_response({"error": "Vui lòng nhập username"}, status=400)
    
    if "locket.cam/" in username:
        username = username.split("locket.cam/")[-1].split("?")[0]
    
    uid, avatar, name = await locket.resolve_uid_with_avatar(username)
    if not uid:
        return web.json_response({"error": "Không tìm thấy user"}, status=404)
    
    status = await locket.check_status(uid)
    is_gold = status and status.get("active")
    expires = status.get("expires") if status else None
    
    return web.json_response({
        "uid": uid,
        "username": username,
        "name": name,
        "is_gold": is_gold,
        "expires": expires,
        "avatar": avatar
    })

async def api_activate(request):
    data = await request.json()
    uid = data.get("uid")
    username = data.get("username", "user")
    
    if not uid:
        return web.json_response({"error": "Missing UID"}, status=400)
    
    if uid in active_requests:
        return web.json_response({"error": "Đang xử lý, vui lòng đợi..."}, status=429)
    
    active_requests.add(uid)
    
    token_idx = None
    try:
        # Safely acquire an available token with cooldown enforcement
        token_idx, token_config = await TOKEN_MANAGER.acquire_token(cooldown_seconds=15)
        logs = []
        
        def log_cb(msg):
            clean = msg.replace('\033[95m','').replace('\033[94m','').replace('\033[92m','').replace('\033[93m','').replace('\033[91m','').replace('\033[0m','').replace('\033[1m','')
            logs.append(clean)
        
        success, msg_result = await locket.inject_gold(uid, token_config, log_cb)
        
        dns_pid = None
        dns_link = None
        mobileconfig_url = None
        
        if success:
            pid, link = await nextdns.create_profile(NEXTDNS_KEY, log_cb)
            dns_pid = pid
            dns_link = link
            if pid:
                mobileconfig_url = f"/api/dns/{pid}/{username}"
        
        return web.json_response({
            "success": success,
            "message": msg_result,
            "logs": logs,
            "dns_pid": dns_pid,
            "dns_link": dns_link,
            "mobileconfig_url": mobileconfig_url
        })
    finally:
        if token_idx is not None:
            TOKEN_MANAGER.release_token(token_idx)
        active_requests.discard(uid)

async def api_dns_download(request):
    pid = request.match_info['pid']
    username = request.match_info.get('username', 'user')
    
    filepath = nextdns.generate_mobileconfig(pid, username)
    
    response = web.FileResponse(filepath)
    response.headers['Content-Type'] = 'application/x-apple-aspen-config'
    response.headers['Content-Disposition'] = f'attachment; filename="DNS_{username}.mobileconfig"'
    
    # Cleanup after serving
    async def cleanup():
        await asyncio.sleep(5)
        try: os.remove(filepath)
        except: pass
    asyncio.create_task(cleanup())
    
    return response

async def api_get_logs(request):
    from app import database as db
    try:
        logs = db.get_recent_logs(50)
        return web.json_response({"success": True, "logs": logs})
    except Exception as e:
        return web.json_response({"success": False, "error": str(e)}, status=500)

async def api_clear_logs(request):
    from app import database as db
    try:
        db.clear_logs()
        return web.json_response({"success": True})
    except Exception as e:
        return web.json_response({"success": False, "error": str(e)}, status=500)

def create_web_app():
    app = web.Application()
    
    # Static files
    static_dir = os.path.join(os.path.dirname(__file__), "static")
    os.makedirs(static_dir, exist_ok=True)
    
    app.router.add_get("/", serve_index)
    app.router.add_post("/api/resolve", api_resolve)
    app.router.add_post("/api/activate", api_activate)
    app.router.add_get("/api/dns/{pid}/{username}", api_dns_download)
    app.router.add_get("/api/bot-logs", api_get_logs)
    app.router.add_post("/api/clear-logs", api_clear_logs)
    app.router.add_static("/static/", static_dir)
    
    return app

async def start_web_server(port=8080):
    app = create_web_app()
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, "0.0.0.0", port)
    await site.start()
    print(f"[WEB] Server running at http://0.0.0.0:{port}")
    return runner
