import uuid

from fastapi import APIRouter, Depends, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.core.permissions import require_permission
from app.core.scheduler import run_job_now
from app.core.security import AuthContext, get_auth_context
from app.crud.base import CRUDBase
from app.models.scheduling import ScheduledJob
from app.schemas.scheduling import ScheduledJobCreate, ScheduledJobRead, ScheduledJobUpdate

router = APIRouter(prefix="/scheduled-jobs", tags=["scheduled-jobs"])
crud = CRUDBase[ScheduledJob, ScheduledJobCreate, ScheduledJobUpdate](ScheduledJob)


@router.get("", response_model=list[ScheduledJobRead])
async def list_scheduled_jobs(
    skip: int = 0,
    limit: int = 100,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("tasks", "view")),
) -> list[ScheduledJob]:
    return await crud.list(db, ctx.tenant_id, skip=skip, limit=limit)


@router.get("/{job_id}", response_model=ScheduledJobRead)
async def get_scheduled_job(
    job_id: uuid.UUID,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("tasks", "view")),
) -> ScheduledJob:
    return await crud.get(db, ctx.tenant_id, job_id)


@router.post("", response_model=ScheduledJobRead, status_code=status.HTTP_201_CREATED)
async def create_scheduled_job(
    payload: ScheduledJobCreate,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("tasks", "create")),
) -> ScheduledJob:
    return await crud.create(db, ctx.tenant_id, payload, created_by=ctx.user_id)


@router.patch("/{job_id}", response_model=ScheduledJobRead)
async def update_scheduled_job(
    job_id: uuid.UUID,
    payload: ScheduledJobUpdate,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("tasks", "edit")),
) -> ScheduledJob:
    return await crud.update(db, ctx.tenant_id, job_id, payload)


@router.delete("/{job_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_scheduled_job(
    job_id: uuid.UUID,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("tasks", "delete")),
) -> None:
    await crud.delete(db, ctx.tenant_id, job_id)


@router.post("/{job_id}/run-now", response_model=ScheduledJobRead)
async def run_scheduled_job_now(
    job_id: uuid.UUID,
    ctx: AuthContext = Depends(get_auth_context),
    db: AsyncSession = Depends(get_db),
    _: AuthContext = Depends(require_permission("tasks", "edit")),
) -> ScheduledJob:
    """Runs immediately, outside its normal cadence — same execution path
    app/core/scheduler.py's tick loop uses, so this is also how the Studio
    UI lets an admin try a job without waiting for it to come due."""
    job = await crud.get(db, ctx.tenant_id, job_id)
    await run_job_now(db, ctx.tenant_id, job)
    await db.refresh(job)
    return job
