"""Deep scan re-queues already-completed ImportTasks.

Operator-flagged 2026-05-25: deep scan used to skip everything that
already had a non-failed ImportTask row, making a deep re-scan a no-op
when no new files were added. That defeated the entire point of deep
scan (re-apply sidecar metadata to existing rows). The skip-set now
splits by mode — quick keeps the old "any non-failed" semantics; deep
skips ONLY actively-in-flight statuses.
"""

import pytest
from PIL import Image
from sqlalchemy import func, select

from backend.app.models import ImportBatch, ImportSettings, ImportTask
from backend.app.tasks.scan import scan_directory

pytestmark = pytest.mark.integration


def _img(path):
    path.parent.mkdir(parents=True, exist_ok=True)
    Image.new("RGB", (40, 40), (10, 200, 80)).save(path, "JPEG")


def test_deep_scan_requeues_completed_task(db_sync, tmp_path, monkeypatch):
    """Quick scan then deep scan of the same /import: the file completed
    in the first run should be re-enqueued by the deep run (different
    ImportTask id, same source_path)."""
    import_root = tmp_path / "import"
    settings = db_sync.execute(
        select(ImportSettings).where(ImportSettings.id == 1)
    ).scalar_one()
    settings.import_scan_path = str(import_root)
    db_sync.commit()

    src = import_root / "Mae" / "p.jpg"
    _img(src)

    from backend.app import celery_app

    celery_app.celery.conf.task_always_eager = False  # explicit
    try:
        first_batch_id = scan_directory.run(triggered_by="manual", mode="quick")
        first_task = db_sync.execute(
            select(ImportTask).where(ImportTask.batch_id == first_batch_id)
        ).scalar_one()
        # Simulate the worker having finished it.
        first_task.status = "complete"
        db_sync.commit()

        # Now deep scan: the SAME file should get a NEW ImportTask row.
        second_batch_id = scan_directory.run(triggered_by="manual", mode="deep")
        assert second_batch_id != first_batch_id

        new_tasks_in_second_batch = db_sync.execute(
            select(func.count())
            .select_from(ImportTask)
            .where(ImportTask.batch_id == second_batch_id)
        ).scalar_one()
        assert new_tasks_in_second_batch == 1, (
            "deep scan did not re-queue the completed file"
        )

        # And the second batch's task should be for the same source_path
        # as the first (proves it's a re-queue, not a different file).
        sp = db_sync.execute(
            select(ImportTask.source_path)
            .where(ImportTask.batch_id == second_batch_id)
        ).scalar_one()
        assert sp == str(src)
    finally:
        celery_app.celery.conf.task_always_eager = False


def test_quick_scan_does_not_requeue_completed_task(db_sync, tmp_path):
    """The flip side: quick scan still keeps the old skip semantics —
    a file with a completed ImportTask row from a prior batch is NOT
    re-enqueued on a fresh quick scan."""
    import_root = tmp_path / "import"
    settings = db_sync.execute(
        select(ImportSettings).where(ImportSettings.id == 1)
    ).scalar_one()
    settings.import_scan_path = str(import_root)
    db_sync.commit()

    src = import_root / "Mae" / "q.jpg"
    _img(src)

    first_batch_id = scan_directory.run(triggered_by="manual", mode="quick")
    first_task = db_sync.execute(
        select(ImportTask).where(ImportTask.batch_id == first_batch_id)
    ).scalar_one()
    first_task.status = "complete"
    db_sync.commit()

    second_batch_id = scan_directory.run(triggered_by="manual", mode="quick")
    second_batch_count = db_sync.execute(
        select(func.count())
        .select_from(ImportTask)
        .where(ImportTask.batch_id == second_batch_id)
    ).scalar_one()
    assert second_batch_count == 0, (
        "quick scan re-queued an already-completed task — should have skipped"
    )

    # And the second batch should self-finalize (files_seen=0).
    second_batch = db_sync.get(ImportBatch, second_batch_id)
    assert second_batch.status == "complete"
