from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from backend.app.api import deps
from backend.app.core.database import get_db
from backend.app.models import sql_models
from backend.app.schemas import schemas
from backend.app.services.scheduler import update_job, run_analysis_pipeline

router = APIRouter()

@router.get("", response_model=List[schemas.Task])
def read_tasks(
    db: Session = Depends(get_db),
    skip: int = 0,
    limit: int = 100,
    current_user: sql_models.User = Depends(deps.get_current_user)
) -> Any:
    return db.query(sql_models.Task).offset(skip).limit(limit).all()

@router.post("", response_model=schemas.Task)
def create_task(
    *,
    db: Session = Depends(get_db),
    task_in: schemas.TaskCreate,
    current_user: sql_models.User = Depends(deps.get_current_user)
) -> Any:
    task = sql_models.Task(**task_in.model_dump())
    db.add(task)
    db.commit()
    db.refresh(task)
    return task

@router.put("/{id}", response_model=schemas.Task)
def update_task(
    *,
    db: Session = Depends(get_db),
    id: int,
    task_in: schemas.TaskUpdate,
    current_user: sql_models.User = Depends(deps.get_current_user)
) -> Any:
    task = db.query(sql_models.Task).filter(sql_models.Task.id == id).first()
    if not task:
        raise HTTPException(status_code=404, detail="Task not found")
    
    # Update fields
    for key, value in task_in.model_dump().items():
        setattr(task, key, value)
    
    db.commit()
    db.refresh(task)
    
    # Update scheduler if running
    if task.is_running:
        update_job(task.id, task.cron_expression, True)
    
    return task

@router.delete("/{id}", response_model=schemas.Task)
def delete_task(
    *,
    db: Session = Depends(get_db),
    id: int,
    current_user: sql_models.User = Depends(deps.get_current_user)
) -> Any:
    task = db.query(sql_models.Task).filter(sql_models.Task.id == id).first()
    if not task:
        raise HTTPException(status_code=404, detail="Task not found")
    
    # Stop scheduler
    update_job(task.id, task.cron_expression, False)
    
    # Delete associated logs first
    db.query(sql_models.TaskLog).filter(sql_models.TaskLog.task_id == id).delete()
    
    db.delete(task)
    db.commit()
    return task

@router.post("/{id}/toggle", response_model=schemas.Task)
def toggle_task(
    *,
    db: Session = Depends(get_db),
    id: int,
    toggle_in: schemas.TaskToggle,
    current_user: sql_models.User = Depends(deps.get_current_user)
) -> Any:
    task = db.query(sql_models.Task).filter(sql_models.Task.id == id).first()
    if not task:
        raise HTTPException(status_code=404, detail="Task not found")
    
    task.is_running = toggle_in.running
    db.commit()
    db.refresh(task)
    
    update_job(task.id, task.cron_expression, task.is_running)
    
    return task

@router.post("/test")
async def test_task(
    *,
    db: Session = Depends(get_db),
    task_in: schemas.TaskTest,
    current_user: sql_models.User = Depends(deps.get_current_user)
) -> Any:
    # 1. Get Model Config
    model_config = db.query(sql_models.ModelConfig).filter(sql_models.ModelConfig.id == task_in.model_config_id).first()
    if not model_config:
        raise HTTPException(status_code=404, detail="Model configuration not found")

    # 2. Run Pipeline (without saving to DB, or maybe we want to save logs for test? 
    # User requirement: "Output logs to console". 
    # Let's execute the pipeline. run_analysis_pipeline can skip DB save if we add a param, 
    # but currently it saves. Saving test logs to DB is actually fine/useful.)
    
    # We will use task_id=0 for temporary test or just pass dummy ID. 
    # But run_analysis_pipeline writes log with task_id. 
    # If we pass 0, it might violate FK if we save to DB.
    # So for test, we might NOT save to DB to avoid FK error, or we create a dummy task.
    # Let's modify run_analysis_pipeline to optionally save to DB.
    
    # Wait, I already updated scheduler.py to accept save_to_db param.
    
    results = await run_analysis_pipeline(
        task_id=0, # Dummy ID, won't be used if save_to_db=False
        camera_ids=task_in.camera_ids,
        model_config=model_config,
        rules=task_in.rules,
        save_to_db=False # Don't save test runs to DB to avoid polluting logs/FK issues
    )
    
    return {"status": "success", "results": results}
