"""YakPanel - Crontab API"""
import tempfile
import os
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from pydantic import BaseModel

from app.core.database import get_db
from app.core.utils import exec_shell_sync
from app.api.auth import get_current_user
from app.models.user import User
from app.models.crontab import Crontab

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


class CreateCrontabRequest(BaseModel):
    name: str = ""
    type: str = "shell"
    schedule: str
    execstr: str


@router.get("/list")
async def crontab_list(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """List cron jobs"""
    result = await db.execute(select(Crontab).order_by(Crontab.id))
    rows = result.scalars().all()
    return [{"id": r.id, "name": r.name, "type": r.type, "schedule": r.schedule, "execstr": r.execstr} for r in rows]


@router.post("/create")
async def crontab_create(
    body: CreateCrontabRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Create cron job"""
    cron = Crontab(name=body.name, type=body.type, schedule=body.schedule, execstr=body.execstr)
    db.add(cron)
    await db.commit()
    return {"status": True, "msg": "Cron job created", "id": cron.id}


@router.post("/apply")
async def crontab_apply(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Sync panel cron jobs to system crontab (root)"""
    result = await db.execute(select(Crontab).order_by(Crontab.id))
    rows = result.scalars().all()
    lines = [
        "# YakPanel managed crontab - do not edit manually",
        "",
    ]
    for r in rows:
        if r.name:
            lines.append(f"# {r.name}")
        lines.append(f"{r.schedule} {r.execstr}")
        lines.append("")
    content = "\n".join(lines).strip() + "\n"
    fd, path = tempfile.mkstemp(suffix=".crontab", prefix="cit_")
    try:
        os.write(fd, content.encode("utf-8"))
        os.close(fd)
        out, err = exec_shell_sync(f"crontab {path}", timeout=10)
        if err and "error" in err.lower():
            raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    finally:
        if os.path.exists(path):
            os.unlink(path)
    return {"status": True, "msg": "Crontab applied", "count": len(rows)}


@router.put("/{cron_id}")
async def crontab_update(
    cron_id: int,
    body: CreateCrontabRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Update cron job"""
    result = await db.execute(select(Crontab).where(Crontab.id == cron_id))
    cron = result.scalar_one_or_none()
    if not cron:
        raise HTTPException(status_code=404, detail="Cron job not found")
    cron.name = body.name
    cron.type = body.type
    cron.schedule = body.schedule
    cron.execstr = body.execstr
    await db.commit()
    return {"status": True, "msg": "Cron job updated"}


@router.delete("/{cron_id}")
async def crontab_delete(
    cron_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Delete cron job"""
    result = await db.execute(select(Crontab).where(Crontab.id == cron_id))
    cron = result.scalar_one_or_none()
    if not cron:
        raise HTTPException(status_code=404, detail="Cron job not found")
    await db.delete(cron)
    await db.commit()
    return {"status": True, "msg": "Cron job deleted"}
