# New file: api/job_management.py
from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks
from typing import Dict, Any, Optional
from datetime import datetime
from uuid import UUID
import json
import os
import redis.asyncio as aioredis
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_, func

from ..auth import get_current_account
from ..models import Job, JobStatus
from ..db import get_session
from ..storage import get_storage_backend

router = APIRouter(prefix="/api/v1/jobs", tags=["Job Management"])


@router.post("/{job_id}/cancel", summary="Cancel a job")
async def cancel_job(
    job_id: str,
    account_id: UUID = Depends(get_current_account),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """
    Cancel a queued or running job.
    """
    job = await db.get(Job, UUID(job_id))

    if not job:
        raise HTTPException(404, "Job not found")

    if job.account_id != account_id:
        raise HTTPException(403, "Access denied")

    if job.status in [JobStatus.COMPLETED, JobStatus.FAILED, JobStatus.CANCELLED]:
        raise HTTPException(400, f"Cannot cancel job with status: {job.status.value}")

    # Update job status
    job.status = JobStatus.CANCELLED
    job.updated_at = datetime.utcnow()
    job.error = "Cancelled by user"

    db.add(job)
    await db.commit()

    # Send cancel signal to worker
    redis_client = aioredis.from_url(os.getenv("REDIS_URL", "redis://localhost:6379"))
    await redis_client.set(f"job:cancel:{job_id}", "1", ex=3600)

    # Emit progress event
    await redis_client.xadd(
        f"progress:{job_id}",
        {
            "event": json.dumps(
                {
                    "job_id": job_id,
                    "phase": "cancelled",
                    "percent": 100,
                    "message": "Job cancelled by user",
                }
            )
        },
    )

    await redis_client.close()

    return {
        "job_id": job_id,
        "status": "cancelled",
        "message": "Job cancellation requested",
    }


@router.post("/{job_id}/retry", summary="Retry a failed job")
async def retry_job(
    job_id: str,
    account_id: UUID = Depends(get_current_account),
    db: AsyncSession = Depends(get_session),
    background_tasks: BackgroundTasks = BackgroundTasks(),
) -> Dict[str, Any]:
    """
    Retry a failed job with the same configuration.
    """
    job = await db.get(Job, UUID(job_id))

    if not job:
        raise HTTPException(404, "Job not found")

    if job.account_id != account_id:
        raise HTTPException(403, "Access denied")

    if job.status != JobStatus.FAILED:
        raise HTTPException(
            400, f"Can only retry failed jobs. Current status: {job.status.value}"
        )

    # Reset job status
    job.status = JobStatus.QUEUED
    job.error = None
    job.retry_count = (job.retry_count or 0) + 1
    job.updated_at = datetime.utcnow()

    db.add(job)
    await db.commit()

    # Re-queue the job
    from rq import Queue
    import redis

    redis_conn = redis.from_url(os.getenv("REDIS_URL", "redis://localhost:6379"))
    q = Queue("default", connection=redis_conn)

    q.enqueue(
        "fmatch.saas.worker.run_matching_job", str(job.id), job_timeout="1h", retry=True
    )

    return {
        "job_id": str(job.id),
        "status": "queued",
        "retry_count": job.retry_count,
        "message": "Job queued for retry",
    }


@router.get("/", summary="List jobs")
async def list_jobs(
    status: Optional[JobStatus] = None,
    limit: int = 50,
    offset: int = 0,
    account_id: UUID = Depends(get_current_account),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, Any]:
    """
    List jobs for the current account with filtering.
    """
    # Build query
    conditions = [Job.account_id == account_id]

    if status:
        conditions.append(Job.status == status)

    # Count total
    count_stmt = select(func.count()).select_from(Job).where(and_(*conditions))
    total_count = await db.scalar(count_stmt)

    # Get paginated results
    stmt = (
        select(Job)
        .where(and_(*conditions))
        .order_by(Job.created_at.desc())
        .offset(offset)
        .limit(limit)
    )

    result = await db.execute(stmt)
    jobs = result.scalars().all()

    return {
        "total": total_count,
        "offset": offset,
        "limit": limit,
        "jobs": [
            {
                "id": str(job.id),
                "type": job.type.value if job.type else None,
                "status": job.status.value if job.status else None,
                "created_at": job.created_at.isoformat() if job.created_at else None,
                "updated_at": job.updated_at.isoformat() if job.updated_at else None,
                "matches_found": job.matches_found,
                "error": job.error,
                "retry_count": job.retry_count,
            }
            for job in jobs
        ],
    }


@router.delete("/{job_id}", summary="Delete a job")
async def delete_job(
    job_id: str,
    delete_results: bool = False,
    account_id: UUID = Depends(get_current_account),
    db: AsyncSession = Depends(get_session),
) -> Dict[str, str]:
    """
    Delete a job and optionally its results.
    """
    job = await db.get(Job, UUID(job_id))

    if not job:
        raise HTTPException(404, "Job not found")

    if job.account_id != account_id:
        raise HTTPException(403, "Access denied")

    # Delete results if requested
    if delete_results and job.results_path:
        try:
            storage = get_storage_backend()
            await storage.delete(job.results_path)
        except Exception as e:
            # Log but don't fail
            import logging

            logging.error(f"Failed to delete results for job {job_id}: {e}")

    # Delete job record
    await db.delete(job)
    await db.commit()

    return {"message": f"Job {job_id} deleted successfully"}
