from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse, JSONResponse
from dotenv import load_dotenv
from pathlib import Path
import os
import requests
import subprocess
import time

from app.auth import get_room_name

load_dotenv()

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Mount the static directory
app.mount("/static", StaticFiles(directory="frontend/out", html=True), name="static")

def _create_room():
    api_path = os.getenv("DAILY_API_PATH") or "https://api.daily.co/v1"
    expiry_time = os.getenv("BOT_MAX_DURATION", 300)
    daily_api_key = os.getenv("DAILY_API_KEY", None)

    try:
        res = requests.post(
            f"{api_path}/rooms",
            headers={"Authorization": f"Bearer {daily_api_key}"},
            json={
                "properties": {
                    "exp": time.time() + int(expiry_time),
                    "eject_at_room_exp": True,
                    "enable_prejoin_ui": False,
                    "start_audio_off": True,
                    "permissions": {
                        "canSend": ["video"]
                    }
                }
            }
        )
        if res.status_code != 200:
            return JSONResponse({
                "error": "Unable to create room",
                "status_code": res.status_code,
                "text": res.text
            }, 500)
        
        data = res.json()
        print(data)
        return JSONResponse({"room_url": data["url"], "privacy": data["privacy"]})
    
    except Exception:
        return JSONResponse({"error": Exception})
        

def _start_bot(bot_path, room_url, args=None):
    daily_room_name = get_room_name(room_url)
    daily_api_path = os.getenv("DAILY_API_PATH")
    daily_api_key = os.getenv("DAILY_API_KEY")

    #@TODO error handling here

    if args:
        extra_args = " ".join([f'-{x[0]} "{x[1]}"' for x in args])
    else:
        extra_args = ""

    proc = subprocess.Popen(
        [
            f"python3 {bot_path} -u {room_url} -k {daily_api_key} {extra_args}"
        ],
        shell=True,
        bufsize=1,
    )

    # Don't return until the bot has joined the room, but wait for at most 2 seconds.
    attempts = 0
    while attempts < 20:
        time.sleep(0.1)
        attempts += 1
        res = requests.get(
            f"{daily_api_path}/rooms/{daily_room_name}/get-session-data",
            headers={"Authorization": f"Bearer {daily_api_key}"},
        )
        if res.status_code == 200:
            break
    print(f"Took {attempts} attempts to join room {daily_room_name}")

    return JSONResponse({"started": True})


@app.post("/start")
async def start(request: Request):
    data = await request.json()
    return _start_bot("./app/bot.py", data['room_url'])

@app.post("/create")
async def create():
    return _create_room()

@app.get("/{path_name:path}", response_class=FileResponse)
async def catch_all(path_name: str):
    if path_name == "":
        return FileResponse("frontend/out/index.html")

    file_path = Path("frontend/out") / path_name

    if file_path.is_file():
        return file_path

    html_file_path = file_path.with_suffix(".html")
    if html_file_path.is_file():
        return FileResponse(html_file_path)

    raise HTTPException(status_code=450, detail="Incorrect API call")

# Run the application using Uvicorn
if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        "server:app",
        host="0.0.0.0",
        port=int(os.getenv('FAST_API_PORT', 8000)),
        reload=os.getenv('FAST_API_RELOAD', 'false').lower() == 'true',
        #ssl_certfile=args.ssl_certfile,
        #ssl_keyfile=args.ssl_keyfile,
    )