from datetime import datetime

import pytest
import time_machine
from scrobbles import tasks as scrobbles_tasks


class FakeWebDAVClient:
    def __init__(self, files=None):
        self.files = files if files is not None else {}
        self.uploaded = []

    def mkdir(self, path, recursive=False):
        self.files.setdefault(path, None)

    def upload_sync(self, remote_path, local_path):
        with open(local_path, "rb") as f:
            self.files[remote_path] = f.read()
        self.uploaded.append(remote_path)

    def list(self, remote_path, get_info=False):
        names = [
            k for k in self.files if k.startswith(remote_path) and k != remote_path
        ]
        if get_info:
            return [{"path": n} for n in names]
        return names

    def clean(self, remote_path):
        self.files.pop(remote_path, None)


@pytest.fixture
def fake_webdav_client():
    return FakeWebDAVClient()


def test_retention_files_to_delete_keeps_recent_and_monthly():
    now = datetime(2026, 8, 10)
    files = [
        "vrobbler-backup-2026_08_10.sql.gz",
        "vrobbler-backup-2026_08_09.sql.gz",
        "vrobbler-backup-2026_08_01.sql.gz",
        "vrobbler-backup-2026_07_31.sql.gz",
        "vrobbler-backup-2026_07_01.sql.gz",
        "vrobbler-backup-2026_06_15.sql.gz",
        "vrobbler-backup-2026_06_02.sql.gz",
        "not-a-backup.txt",
    ]
    to_delete = scrobbles_tasks._retention_files_to_delete(files, now)

    assert "vrobbler-backup-2026_08_10.sql.gz" not in to_delete
    assert "vrobbler-backup-2026_08_09.sql.gz" not in to_delete
    assert "vrobbler-backup-2026_08_01.sql.gz" not in to_delete
    assert "vrobbler-backup-2026_07_31.sql.gz" not in to_delete
    assert "vrobbler-backup-2026_06_15.sql.gz" not in to_delete
    assert "not-a-backup.txt" not in to_delete

    assert "vrobbler-backup-2026_07_01.sql.gz" in to_delete
    assert "vrobbler-backup-2026_06_02.sql.gz" in to_delete


@time_machine.travel(datetime(2026, 8, 10))
def test_run_webdav_cleanup_prunes_old_backups(fake_webdav_client):
    path = "var/vrobbler-backups/"
    fake_webdav_client.files = {
        f"{path}vrobbler-backup-2026_08_10.sql.gz": b"new",
        f"{path}vrobbler-backup-2026_07_31.sql.gz": b"monthly",
        f"{path}vrobbler-backup-2026_07_01.sql.gz": b"old",
    }

    summary = scrobbles_tasks._run_webdav_cleanup(fake_webdav_client, path)

    assert summary == "pruned 1 old webdav backup(s)"
    assert f"{path}vrobbler-backup-2026_08_10.sql.gz" in fake_webdav_client.files
    assert f"{path}vrobbler-backup-2026_07_31.sql.gz" in fake_webdav_client.files
    assert f"{path}vrobbler-backup-2026_07_01.sql.gz" not in fake_webdav_client.files


def test_run_webdav_cleanup_no_files(fake_webdav_client):
    assert (
        scrobbles_tasks._run_webdav_cleanup(fake_webdav_client, "var/vrobbler-backups/")
        is None
    )


def test_run_webdav_cleanup_ignores_unrelated_files(fake_webdav_client):
    path = "var/vrobbler-backups/"
    fake_webdav_client.files = {
        f"{path}notes.txt": b"x",
    }
    assert scrobbles_tasks._run_webdav_cleanup(fake_webdav_client, path) is None
