from datetime import datetime, timezone

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session

from app.api.deps import require_admin
from app.core.database import get_db
from app.models import (
    Application,
    Job,
    JobSource,
    Plan,
    UpgradeRequest,
    User,
)
from app.schemas.billing import (
    AdminStatsOut,
    AdminUserOut,
    AssignPlanIn,
    PlanOut,
    PlanUpdateIn,
    UpgradeRequestOut,
)
from app.schemas import JobSourceOut, JobSourceUpdate
from app.services.entitlements import assign_plan, get_plan_for_user

router = APIRouter(prefix="/admin", tags=["admin"])


@router.get("/stats", response_model=AdminStatsOut)
def stats(admin: User = Depends(require_admin), db: Session = Depends(get_db)):
    return AdminStatsOut(
        users=db.query(User).count(),
        jobs=db.query(Job).count(),
        sources=db.query(JobSource).count(),
        sources_enabled=db.query(JobSource).filter(JobSource.enabled.is_(True)).count(),
        pending_upgrades=db.query(UpgradeRequest).filter(UpgradeRequest.status == "pending").count(),
        applications=db.query(Application).count(),
    )


@router.get("/plans", response_model=list[PlanOut])
def admin_list_plans(admin: User = Depends(require_admin), db: Session = Depends(get_db)):
    return db.query(Plan).order_by(Plan.sort_order.asc()).all()


@router.patch("/plans/{plan_key}", response_model=PlanOut)
def admin_update_plan(
    plan_key: str,
    payload: PlanUpdateIn,
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    plan = db.query(Plan).filter(Plan.key == plan_key).first()
    if not plan:
        raise HTTPException(404, "Plan no encontrado")
    data = payload.model_dump(exclude_unset=True)
    for k, v in data.items():
        setattr(plan, k, v)
    plan.updated_at = datetime.now(timezone.utc)
    db.commit()
    db.refresh(plan)
    return plan


@router.get("/users", response_model=list[AdminUserOut])
def admin_list_users(admin: User = Depends(require_admin), db: Session = Depends(get_db)):
    users = db.query(User).order_by(User.created_at.desc()).limit(500).all()
    out: list[AdminUserOut] = []
    for u in users:
        plan = get_plan_for_user(db, u)
        out.append(
            AdminUserOut(
                id=u.id,
                email=u.email,
                name=u.name,
                is_admin=u.is_admin,
                is_active=u.is_active,
                plan_key=plan.key if plan else None,
                plan_name=plan.name if plan else None,
                created_at=u.created_at,
            )
        )
    return out


@router.post("/users/{user_id}/assign-plan", response_model=AdminUserOut)
def admin_assign_plan(
    user_id: int,
    payload: AssignPlanIn,
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    user = db.get(User, user_id)
    if not user:
        raise HTTPException(404, "Usuario no encontrado")
    plan = db.query(Plan).filter(Plan.key == payload.plan_key).first()
    if not plan:
        raise HTTPException(404, "Plan no encontrado")
    assign_plan(db, user, plan, note=payload.notes or f"Asignado por {admin.email}")
    plan = get_plan_for_user(db, user)
    return AdminUserOut(
        id=user.id,
        email=user.email,
        name=user.name,
        is_admin=user.is_admin,
        is_active=user.is_active,
        plan_key=plan.key,
        plan_name=plan.name,
        created_at=user.created_at,
    )


@router.get("/upgrade-requests", response_model=list[UpgradeRequestOut])
def admin_upgrade_requests(
    status: str | None = "pending",
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    q = db.query(UpgradeRequest).order_by(UpgradeRequest.created_at.desc())
    if status:
        q = q.filter(UpgradeRequest.status == status)
    rows = q.limit(200).all()
    out: list[UpgradeRequestOut] = []
    for r in rows:
        u = db.get(User, r.user_id)
        p = db.get(Plan, r.plan_id)
        out.append(
            UpgradeRequestOut(
                id=r.id,
                user_id=r.user_id,
                plan_id=r.plan_id,
                status=r.status,
                message=r.message,
                admin_note=r.admin_note,
                created_at=r.created_at,
                resolved_at=r.resolved_at,
                user_email=u.email if u else None,
                plan_key=p.key if p else None,
                plan_name=p.name if p else None,
            )
        )
    return out


@router.post("/upgrade-requests/{req_id}/approve", response_model=UpgradeRequestOut)
def approve_upgrade(
    req_id: int,
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    req = db.get(UpgradeRequest, req_id)
    if not req:
        raise HTTPException(404, "Solicitud no encontrada")
    user = db.get(User, req.user_id)
    plan = db.get(Plan, req.plan_id)
    if not user or not plan:
        raise HTTPException(400, "Usuario o plan inválido")
    assign_plan(db, user, plan, note=f"Aprobado por {admin.email}")
    req.status = "approved"
    req.admin_note = f"Aprobado por {admin.email}"
    req.resolved_at = datetime.now(timezone.utc)
    db.commit()
    db.refresh(req)
    return UpgradeRequestOut(
        id=req.id,
        user_id=req.user_id,
        plan_id=req.plan_id,
        status=req.status,
        message=req.message,
        admin_note=req.admin_note,
        created_at=req.created_at,
        resolved_at=req.resolved_at,
        user_email=user.email,
        plan_key=plan.key,
        plan_name=plan.name,
    )


@router.post("/upgrade-requests/{req_id}/reject", response_model=UpgradeRequestOut)
def reject_upgrade(
    req_id: int,
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    req = db.get(UpgradeRequest, req_id)
    if not req:
        raise HTTPException(404, "Solicitud no encontrada")
    user = db.get(User, req.user_id)
    plan = db.get(Plan, req.plan_id)
    req.status = "rejected"
    req.admin_note = f"Rechazado por {admin.email}"
    req.resolved_at = datetime.now(timezone.utc)
    db.commit()
    db.refresh(req)
    return UpgradeRequestOut(
        id=req.id,
        user_id=req.user_id,
        plan_id=req.plan_id,
        status=req.status,
        message=req.message,
        admin_note=req.admin_note,
        created_at=req.created_at,
        resolved_at=req.resolved_at,
        user_email=user.email if user else None,
        plan_key=plan.key if plan else None,
        plan_name=plan.name if plan else None,
    )


@router.get("/sources", response_model=list[JobSourceOut])
def admin_sources(admin: User = Depends(require_admin), db: Session = Depends(get_db)):
    return db.query(JobSource).order_by(JobSource.priority.asc(), JobSource.name.asc()).all()


@router.patch("/sources/{key}", response_model=JobSourceOut)
def admin_update_source(
    key: str,
    payload: JobSourceUpdate,
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    src = db.query(JobSource).filter(JobSource.key == key).first()
    if not src:
        raise HTTPException(404, "Fuente no encontrada")
    if payload.enabled is not None:
        src.enabled = payload.enabled
    if payload.config is not None:
        src.config = payload.config
    db.commit()
    db.refresh(src)
    return src


@router.get("/health")
def admin_health(
    deep: bool = False,
    admin: User = Depends(require_admin),
    db: Session = Depends(get_db),
):
    from app.services.health import run_full_health

    return run_full_health(db, admin, deep=deep)


@router.post("/demo-pack")
def admin_demo_pack(admin: User = Depends(require_admin), db: Session = Depends(get_db)):
    from app.services.health import seed_demo_pack

    return seed_demo_pack(db, admin)


@router.post("/demo-mode")
def admin_demo_mode(admin: User = Depends(require_admin), db: Session = Depends(get_db)):
    from app.services.wow_tier_a import run_demo_mode

    return run_demo_mode(db, admin)
