from fastapi import FastAPI, Query, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import asyncio
import tempfile
import json
import os
from typing import Optional
import uvicorn
from scrape_instagram_reels import run_scraper

app = FastAPI(title="Instagram Reel Scraper API with Rate Limiting")

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

# Semaphore mit einem Limit von 1, um nur eine Aufgabe gleichzeitig zu erlauben
scraper_semaphore = asyncio.Semaphore(1)

@app.get("/")
def root():
    return {"message": "Instagram Reels Scraper API is running."}

@app.get("/reels")
async def get_reels_with_limit(
    username: str = Query(...),
    reels: int = Query(20, ge=1, le=1000),
    output_format: str = Query("json", pattern="^(json|csv)$"),
    profile_id: Optional[str] = Query(None),
    token: Optional[str] = Query(None)
):
    # Versuche, die Semaphore zu erwerben.
    # Wenn sie bereits von einer anderen Anfrage gehalten wird, schlage fehl.
    if scraper_semaphore.locked():
        raise HTTPException(
            status_code=429,
            detail="Too many requests. Another scraping task is already in progress. Please try again later."
        )

    # Erwerbe die Semaphore, um zu signalisieren, dass eine Aufgabe läuft
    await scraper_semaphore.acquire()

    # Erstelle eine temporäre Datei
    with tempfile.NamedTemporaryFile(suffix=f".{output_format}", delete=False) as tmp_file:
        output_path = tmp_file.name

    try:
        # Führe die Scraping-Funktion in einem separaten Thread aus
        # um die API nicht zu blockieren, während auf die E/A gewartet wird
        await asyncio.to_thread(
            run_scraper,
            username=username,
            count=reels,
            output=output_path,
            delay=0.5,
            profile_id=profile_id,
            token=token,
        )

        # Lese das Ergebnis aus der Datei
        if output_format == "json":
            with open(output_path, encoding="utf-8") as f:
                data = json.load(f)
            return {"status": "done", "result": data}
        else:
            with open(output_path, encoding="utf-8") as f:
                csv_data = f.read()
            return {"status": "done", "csv_result": csv_data}

    except Exception as e:
        # Bei einem Fehler eine HTTPException auslösen
        raise HTTPException(status_code=500, detail=f"Scraping failed: {e}")

    finally:
        # Gib die Semaphore frei, damit die nächste Anfrage verarbeitet werden kann
        scraper_semaphore.release()
        # Temporäre Datei löschen
        os.remove(output_path)

if __name__ == "__main__":
    uvicorn.run("api_server:app", host="0.0.0.0", port=8080, reload=True)