"""Bulk download job management (in-memory)."""

import uuid
import threading
import logging
from datetime import datetime

from backend.services.downloader import VideoDownloader
from backend.services.sora_downloader import SoraDownloader

logger = logging.getLogger("viral_social.bulk_download")


# ── In-memory job store ──────────────────────────────────────────
_jobs: dict[str, dict] = {}
_jobs_lock = threading.Lock()

MAX_CONCURRENT_JOBS = 3
MAX_URLS_PER_JOB = 500


def create_bulk_job(urls: list[str], quality: str = "best") -> dict:
    """
    Create a new bulk download job.

    Returns the initial job status dict.
    Raises ValueError if validation fails.
    """
    urls = [u.strip() for u in urls if u.strip()]
    if not urls:
        raise ValueError("Nenhuma URL válida fornecida")
    if len(urls) > MAX_URLS_PER_JOB:
        raise ValueError(f"Máximo de {MAX_URLS_PER_JOB} URLs por vez")

    active = sum(1 for j in _jobs.values() if j["status"] == "running")
    if active >= MAX_CONCURRENT_JOBS:
        raise ValueError(
            "Limite de downloads simultâneos atingido. Aguarde os anteriores."
        )

    job_id = uuid.uuid4().hex[:12]

    job = {
        "job_id": job_id,
        "status": "running",
        "quality": quality,
        "created_at": datetime.utcnow().isoformat(),
        "completed_at": None,
        "urls": [
            {
                "url": url,
                "status": "pending",
                "filename": "",
                "path": "",
                "size_formatted": "",
                "error": "",
            }
            for url in urls
        ],
        "total": len(urls),
        "done": 0,
        "errors": 0,
    }

    with _jobs_lock:
        _jobs[job_id] = job

    thread = threading.Thread(
        target=_process_job,
        args=(job_id,),
        daemon=True,
        name=f"bulk-download-{job_id}",
    )
    thread.start()

    return get_job_status(job_id)


def get_job_status(job_id: str) -> dict | None:
    """Get the current status of a bulk download job."""
    job = _jobs.get(job_id)
    if not job:
        return None

    return {
        "job_id": job["job_id"],
        "status": job["status"],
        "total": job["total"],
        "done": job["done"],
        "errors": job["errors"],
        "created_at": job["created_at"],
        "completed_at": job["completed_at"],
        "urls": [
            {
                "url": entry["url"],
                "status": entry["status"],
                "filename": entry["filename"],
                "path": entry["path"],
                "size_formatted": entry["size_formatted"],
                "error": entry["error"],
            }
            for entry in job["urls"]
        ],
    }


def cancel_job(job_id: str) -> bool:
    """Cancel a running job. Current download finishes, rest are skipped."""
    job = _jobs.get(job_id)
    if not job or job["status"] != "running":
        return False
    job["status"] = "cancelled"
    return True


# ── Background processing ────────────────────────────────────────

def _detect_platform(url: str) -> str:
    """Detect platform from URL."""
    url_lower = url.lower()
    if "youtube.com" in url_lower or "youtu.be" in url_lower:
        return "youtube"
    if "tiktok.com" in url_lower:
        return "tiktok"
    if "instagram.com" in url_lower:
        return "instagram"
    if "sora.chatgpt.com" in url_lower or "sora.com" in url_lower:
        return "sora"
    return "unknown"


def _process_job(job_id: str):
    """Process all URLs in a bulk download job sequentially."""
    job = _jobs.get(job_id)
    if not job:
        return

    downloader = VideoDownloader()
    sora_downloader = SoraDownloader()

    for i, entry in enumerate(job["urls"]):
        # Check if cancelled
        if job["status"] == "cancelled":
            for remaining in job["urls"][i:]:
                if remaining["status"] == "pending":
                    remaining["status"] = "error"
                    remaining["error"] = "Download cancelado"
                    job["errors"] += 1
            break

        url = entry["url"]
        entry["status"] = "downloading"
        platform = _detect_platform(url)

        try:
            if SoraDownloader.is_sora_url(url):
                result = sora_downloader.download(url, quality=job["quality"])
            else:
                result = downloader.download(
                    url=url,
                    platform=platform,
                    quality=job["quality"],
                )

            if result["success"]:
                entry["status"] = "done"
                entry["filename"] = result["filename"]
                entry["path"] = result["path"]
                entry["size_formatted"] = result["size_formatted"]
                job["done"] += 1
            else:
                entry["status"] = "error"
                entry["error"] = result.get("error", "Erro desconhecido")
                job["errors"] += 1

        except Exception as e:
            entry["status"] = "error"
            entry["error"] = str(e)
            job["errors"] += 1
            logger.error(f"Bulk download error for {url}: {e}")

    if job["status"] != "cancelled":
        job["status"] = "completed"
    job["completed_at"] = datetime.utcnow().isoformat()

    logger.info(
        f"Bulk job {job_id} finished: "
        f"{job['done']}/{job['total']} ok, {job['errors']} errors"
    )
