"""Unit tests for the S3 ingestion cache startup sweep (QUE-223).

The sweep is pure filesystem and keyed off atime, so these tests need no S3 /
moto: we create files, set their atime with ``os.utime``, and assert which
ones the sweep reclaims. Source-change (ETag) behavior is cloudpathlib's own
and is not re-tested here.
"""

from __future__ import annotations

import os
import subprocess
import sys
import time
from pathlib import Path

import pytest

from quber.files.cache import evict_stale_s3_cache, resolve_artifacts, resolve_document


def test_evict_removes_only_stale_files(tmp_path: Path):
    ttl = 1000.0
    now = time.time()

    fresh = tmp_path / "fresh.pdf"
    fresh.write_bytes(b"fresh")
    os.utime(fresh, (now, now))  # atime = now -> within TTL window

    stale = tmp_path / "nested" / "stale.pdf"
    stale.parent.mkdir(parents=True)
    stale.write_bytes(b"stale")
    old = now - ttl - 100
    os.utime(stale, (old, old))  # atime well past TTL

    evicted = evict_stale_s3_cache(tmp_path, ttl)

    assert evicted == 1
    assert fresh.exists()
    assert not stale.exists()


def test_evict_missing_dir_is_noop(tmp_path: Path):
    assert evict_stale_s3_cache(tmp_path / "does-not-exist", 1000.0) == 0


def test_resolve_document_local_passthrough(tmp_path: Path):
    """A local path resolves to the same filesystem Path, untouched (no S3)."""
    local = tmp_path / "doc.pdf"
    local.write_bytes(b"%PDF-1.4")
    resolved = resolve_document(str(local))
    assert resolved == local
    assert resolved.read_bytes() == b"%PDF-1.4"


def test_resolve_artifacts_local_passthrough(tmp_path: Path):
    """A local artifacts directory resolves to itself, untouched (no S3)."""
    (tmp_path / "doc.docling.json").write_text("{}")
    assert resolve_artifacts(str(tmp_path), ["doc.docling.json"]) == tmp_path


def test_resolve_artifacts_s3_materializes_each_named_file(tmp_path: Path, monkeypatch):
    """An s3:// prefix resolves each named file through resolve_document and
    returns their shared local cache directory."""
    import quber.files.cache as cache

    resolved: list[str] = []

    def fake_resolve(raw: str, cache_dir=None) -> Path:
        resolved.append(raw)
        return tmp_path / "bucket" / "prefix" / raw.rsplit("/", 1)[-1]

    monkeypatch.setattr(cache, "resolve_document", fake_resolve)
    out = resolve_artifacts("s3://bucket/prefix", ["a.json", "b.json"])
    assert resolved == ["s3://bucket/prefix/a.json", "s3://bucket/prefix/b.json"]
    assert out == tmp_path / "bucket" / "prefix"


def test_resolve_artifacts_requires_filenames():
    with pytest.raises(ValueError):
        resolve_artifacts("s3://bucket/prefix", [])


def test_import_quber_is_credential_free(tmp_path: Path):
    """`import quber` runs init_s3_cache() (which reads get_settings().s3_cache);
    it must succeed on a host with no AWS credentials and no .env (QUE-228).

    Runs in a subprocess with a scrubbed environment so no ambient AWS creds or
    `.env` can mask a regression, and cwd set to an empty temp dir.
    """
    scrubbed = {
        "PATH": os.environ.get("PATH", ""),
        "HOME": str(tmp_path),  # no ~/.aws under a fresh temp HOME
    }
    result = subprocess.run(
        [sys.executable, "-c", "import quber; print(quber.__version__)"],
        env=scrubbed,
        cwd=tmp_path,
        capture_output=True,
        text=True,
    )
    assert result.returncode == 0, f"import quber failed:\n{result.stderr}"
    assert result.stdout.strip()
