"""Tests for /tmp/nexus_upload_* periodic cleanup."""

import os
import time
from unittest.mock import patch

import pytest

from server.background.upload_staging_cleanup import _cleanup_stale_upload_dirs
from server.utils.posix_paths import UPLOAD_STAGING_PREFIX


@pytest.fixture
def staging_dirs(tmp_path, monkeypatch):
    """Point UPLOAD_STAGING_PREFIX at tmp_path for isolated tests."""
    prefix = str(tmp_path / "nexus_upload_")
    monkeypatch.setattr("server.background.upload_staging_cleanup.UPLOAD_STAGING_PREFIX", prefix)
    monkeypatch.setattr("server.utils.posix_paths.UPLOAD_STAGING_PREFIX", prefix)
    return prefix


def test_cleanup_removes_old_dir(staging_dirs):
    old_dir = staging_dirs + "old123"
    os.makedirs(old_dir)
    old_time = time.time() - (25 * 3600)
    os.utime(old_dir, (old_time, old_time))

    fresh_dir = staging_dirs + "fresh456"
    os.makedirs(fresh_dir)

    removed = _cleanup_stale_upload_dirs()
    assert removed == 1
    assert not os.path.isdir(old_dir)
    assert os.path.isdir(fresh_dir)


def test_cleanup_skips_non_directory(staging_dirs):
    file_path = staging_dirs + "notadir"
    with open(file_path, "w", encoding="utf-8") as f:
        f.write("x")
    assert _cleanup_stale_upload_dirs() == 0
    assert os.path.isfile(file_path)


def test_cleanup_skips_path_outside_prefix(staging_dirs, monkeypatch):
    """realpath must stay under prefix — symlink escape is skipped."""
    safe = staging_dirs + "safe"
    os.makedirs(safe)
    old_time = time.time() - (25 * 3600)
    os.utime(safe, (old_time, old_time))

    outside = os.path.join(os.path.dirname(staging_dirs.rstrip("_")), "outside_escape")
    os.makedirs(outside, exist_ok=True)
    link = staging_dirs + "evil"
    try:
        os.symlink(outside, link)
    except OSError:
        pytest.skip("symlink not supported on this platform")

    with patch("server.background.upload_staging_cleanup.logger"):
        removed = _cleanup_stale_upload_dirs()
    assert removed >= 1
    assert not os.path.isdir(safe)
    assert os.path.isdir(outside)
