"""PLAY CHANNELS API — backend próprio (FastAPI + MongoDB)."""
import logging
import os
from pathlib import Path
from typing import Optional

from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from starlette.middleware.cors import CORSMiddleware

import routes_admin
import routes_vpn
from core import (NO_ID, UPLOAD_DIR, LoginIn, authenticate, client, create_session, db, ensure_indexes,
                  get_current_user, hash_password, now_iso, public_user, revoke_current)
from seed import migrate, seed_database

app = FastAPI(title="PLAY CHANNELS API", docs_url=None, redoc_url=None, openapi_url=None)
logger = logging.getLogger("playchannels")
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')


@app.get("/health", include_in_schema=False)
@app.head("/health", include_in_schema=False)
async def health():
    return {"status": "ok"}


api = APIRouter(prefix="/api")


@api.post("/auth/login")
async def login(body: LoginIn, request: Request):
    user = await authenticate(body, "user", request)
    token, exp = await create_session(user, "user", request)
    return {"token": token, "user": public_user(user), "expires_at": exp}


@api.post("/auth/logout")
async def logout(user: dict = Depends(get_current_user)):
    await revoke_current(user)
    return {"ok": True}


@api.get("/auth/me")
async def me(user: dict = Depends(get_current_user)):
    return public_user(user)


PUBLIC_CONFIG = ("app_name", "logo_url", "background_url", "primary_color", "welcome_message",
                 "maintenance", "maintenance_message", "support_contact")


# ---------------- Public config (remote, no rebuild) ----------------
@api.get("/config")
async def get_config():
    cfg = await db.config.find_one({"key": "app"}, NO_ID) or {}
    return {k: cfg.get(k) for k in PUBLIC_CONFIG}


# ---------------- Content ----------------
@api.get("/home")
async def home(user: dict = Depends(get_current_user)):
    banners = await db.banners.find({"active": True}, NO_ID).sort("order", 1).to_list(20)
    content = await db.content.find({"active": True}, NO_ID).to_list(1000)
    categories = await db.categories.find({}, NO_ID).sort("order", 1).to_list(100)
    rows = []
    for c in categories:
        items = [x for x in content if c["id"] in x.get("category_ids", [])]
        if items:
            rows.append({"id": c["id"], "title": c["name"], "items": items})
    return {
        "banners": banners,
        "featured_movies": [x for x in content if x["type"] == "movie" and x.get("featured")],
        "featured_series": [x for x in content if x["type"] == "series" and x.get("featured")],
        "rows": rows,
    }


@api.get("/categories")
async def list_categories(user: dict = Depends(get_current_user)):
    return await db.categories.find({}, NO_ID).sort("order", 1).to_list(100)


@api.get("/content")
async def list_content(type: Optional[str] = None, category: Optional[str] = None, q: Optional[str] = None,
                       user: dict = Depends(get_current_user)):
    query: dict = {"active": True}
    if type:
        query["type"] = type
    if category:
        query["category_ids"] = category
    if q:
        query["title"] = {"$regex": q, "$options": "i"}
    return await db.content.find(query, NO_ID).to_list(500)


@api.get("/content/{cid}")
async def get_content(cid: str, user: dict = Depends(get_current_user)):
    item = await db.content.find_one({"id": cid}, NO_ID)
    if not item:
        raise HTTPException(404, "Conteúdo não encontrado")
    item["is_favorite"] = bool(await db.favorites.find_one({"user_id": user["id"], "content_id": cid}))
    return item


@api.get("/channels")
async def list_channels(user: dict = Depends(get_current_user)):
    return await db.channels.find({"active": True}, NO_ID).sort("number", 1).to_list(500)


# ---------------- Favorites & history ----------------
@api.get("/favorites")
async def list_favorites(user: dict = Depends(get_current_user)):
    favs = await db.favorites.find({"user_id": user["id"]}, NO_ID).sort("created_at", -1).to_list(500)
    ids = [f["content_id"] for f in favs]
    items = {c["id"]: c for c in await db.content.find({"id": {"$in": ids}}, NO_ID).to_list(500)}
    return [items[i] for i in ids if i in items]


@api.post("/favorites/{cid}")
async def add_favorite(cid: str, user: dict = Depends(get_current_user)):
    if not await db.content.find_one({"id": cid}, NO_ID):
        raise HTTPException(404, "Conteúdo não encontrado")
    await db.favorites.update_one({"user_id": user["id"], "content_id": cid},
                                  {"$setOnInsert": {"user_id": user["id"], "content_id": cid, "created_at": now_iso()}},
                                  upsert=True)
    return {"is_favorite": True}


@api.delete("/favorites/{cid}")
async def remove_favorite(cid: str, user: dict = Depends(get_current_user)):
    await db.favorites.delete_one({"user_id": user["id"], "content_id": cid})
    return {"is_favorite": False}


class HistoryIn(BaseModel):
    content_id: str
    episode_id: Optional[str] = None
    title: str
    image: Optional[str] = None
    stream_url: str
    position: float = 0
    duration: float = 0


@api.get("/history")
async def list_history(user: dict = Depends(get_current_user)):
    return await db.history.find({"user_id": user["id"]}, NO_ID).sort("updated_at", -1).to_list(100)


@api.post("/history")
async def save_history(body: HistoryIn, user: dict = Depends(get_current_user)):
    doc = {**body.model_dump(), "user_id": user["id"], "updated_at": now_iso()}
    await db.history.update_one({"user_id": user["id"], "content_id": body.content_id, "episode_id": body.episode_id},
                                {"$set": doc}, upsert=True)
    return {"ok": True}


@api.delete("/history")
async def clear_history(user: dict = Depends(get_current_user)):
    await db.history.delete_many({"user_id": user["id"]})
    return {"ok": True}


app.include_router(api)
app.include_router(routes_vpn.router)
app.include_router(routes_admin.router)
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
app.mount("/api/media", StaticFiles(directory=str(UPLOAD_DIR)), name="media")
_panel = Path(os.environ["ADMIN_WEB_DIST"])
if _panel.is_dir():
    app.mount("/api/painel", StaticFiles(directory=str(_panel), html=True), name="painel")

app.add_middleware(
    CORSMiddleware,
    allow_origins=[o.strip() for o in os.environ["CORS_ORIGINS"].split(",") if o.strip()],
    allow_credentials=False,  # autenticação por Bearer token, sem cookies (CSRF não se aplica)
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
)


@app.middleware("http")
async def security_headers(request: Request, call_next):
    response = await call_next(request)
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["Referrer-Policy"] = "no-referrer"
    response.headers["X-Frame-Options"] = "DENY"
    if request.url.path.startswith("/api/admin") or request.url.path.startswith("/api/auth"):
        response.headers["Cache-Control"] = "no-store"
    return response


@app.on_event("startup")
async def startup():
    await ensure_indexes()
    await seed_database(db, hash_password, now_iso,
                        os.environ['ADMIN_USERNAME'], os.environ['ADMIN_PASSWORD'],
                        os.environ['DEMO_USERNAME'], os.environ['DEMO_PASSWORD'])
    await migrate(db)


@app.on_event("shutdown")
async def shutdown_db_client():
    client.close()
