"""Tests unitaires pour les algorithmes de rétention (fonctions pures, sans Flask)."""
from datetime import datetime, timedelta


def days_ago(n):
    return datetime.utcnow() - timedelta(days=n)


# ---------------------------------------------------------------------------
# _retention_count
# ---------------------------------------------------------------------------

class TestRetentionCount:
    def test_supprime_les_plus_anciens(self):
        from retention import _retention_count
        archives = [
            "a_20260101.tar", "a_20260102.tar", "a_20260103.tar",
            "a_20260104.tar", "a_20260105.tar",
        ]
        assert _retention_count(archives, 3) == ["a_20260101.tar", "a_20260102.tar"]

    def test_moins_que_n_garde_tout(self):
        from retention import _retention_count
        archives = ["a_20260101.tar", "a_20260102.tar"]
        assert _retention_count(archives, 5) == []

    def test_exactement_n_garde_tout(self):
        from retention import _retention_count
        archives = ["a_20260101.tar", "a_20260102.tar", "a_20260103.tar"]
        assert _retention_count(archives, 3) == []

    def test_liste_vide(self):
        from retention import _retention_count
        assert _retention_count([], 5) == []

    def test_keep_1_supprime_tous_sauf_dernier(self):
        from retention import _retention_count
        archives = ["a_20260101.tar", "a_20260102.tar", "a_20260103.tar"]
        assert _retention_count(archives, 1) == ["a_20260101.tar", "a_20260102.tar"]


# ---------------------------------------------------------------------------
# _retention_daily
# ---------------------------------------------------------------------------

class TestRetentionDaily:
    def test_supprime_archives_trop_anciennes(self):
        from retention import _retention_daily
        archives = [
            f"a_{days_ago(35).strftime('%Y%m%d')}.tar",
            f"a_{days_ago(31).strftime('%Y%m%d')}.tar",
            f"a_{days_ago(10).strftime('%Y%m%d')}.tar",
            f"a_{days_ago(1).strftime('%Y%m%d')}.tar",
        ]
        result = _retention_daily(archives, 30)
        assert archives[0] in result
        assert archives[1] in result
        assert archives[2] not in result
        assert archives[3] not in result

    def test_deduplique_meme_jour(self):
        from retention import _retention_daily
        today = days_ago(0).strftime("%Y%m%d")
        a1 = f"a_{today}.tar"
        a2 = f"a_{today}_2.tar"
        archives = sorted([a1, a2])
        result = _retention_daily(archives, 30)
        assert len(result) == 1

    def test_garde_une_par_jour_dans_fenetre(self):
        from retention import _retention_daily
        archives = [f"a_{days_ago(i).strftime('%Y%m%d')}.tar" for i in range(9, -1, -1)]
        assert _retention_daily(archives, 30) == []

    def test_liste_vide(self):
        from retention import _retention_daily
        assert _retention_daily([], 30) == []

    def test_toutes_hors_fenetre(self):
        from retention import _retention_daily
        archives = [
            f"a_{days_ago(60).strftime('%Y%m%d')}.tar",
            f"a_{days_ago(45).strftime('%Y%m%d')}.tar",
        ]
        result = _retention_daily(archives, 30)
        assert set(result) == set(archives)


# ---------------------------------------------------------------------------
# _retention_gfs
# ---------------------------------------------------------------------------

class TestRetentionGFS:
    def test_liste_vide(self):
        from retention import _retention_gfs
        assert _retention_gfs([], {"daily": 7, "weekly": 4, "monthly": 12}) == []

    def test_tous_dans_fenetre_daily_gardes(self):
        from retention import _retention_gfs
        archives = [f"a_2026050{i}.tar" for i in range(1, 8)]  # 7 archives
        assert _retention_gfs(archives, {"daily": 7, "weekly": 2, "monthly": 2}) == []

    def test_daily_supprime_au_dela_de_n(self):
        from retention import _retention_gfs
        # 15 archives consécutives (mai 01-15), daily=7
        # Le mensuel et hebdo tombent dans la fenêtre daily pour cet exemple
        archives = [f"a_202605{i:02d}.tar" for i in range(1, 16)]
        to_delete = _retention_gfs(archives, {"daily": 7, "weekly": 1, "monthly": 1})
        # Les 7 plus récentes (mai 9-15) sont gardées par daily
        for i in range(9, 16):
            assert f"a_202605{i:02d}.tar" not in to_delete

    def test_monthly_sauve_archive_ancienne(self):
        from retention import _retention_gfs
        # Archives sur 5 mois distincts
        archives = [
            "a_20260115.tar",  # janvier (plus vieux)
            "a_20260215.tar",  # février
            "a_20260315.tar",  # mars
            "a_20260415.tar",  # avril
            "a_20260510.tar",  # mai
            "a_20260511.tar",  # mai (plus récent)
        ]
        # daily=2 garde mai11+mai10, weekly=1 garde semaine de mai11,
        # monthly=3 garde mai→mai11, avr→avr15, mars→mars15
        # Supprimés : jan15, fév15
        to_delete = _retention_gfs(archives, {"daily": 2, "weekly": 1, "monthly": 3})
        assert "a_20260115.tar" in to_delete
        assert "a_20260215.tar" in to_delete
        assert "a_20260315.tar" not in to_delete
        assert "a_20260415.tar" not in to_delete
        assert "a_20260510.tar" not in to_delete
        assert "a_20260511.tar" not in to_delete
        assert len(to_delete) == 2

    def test_weekly_un_seul_representant_par_semaine(self):
        from retention import _retention_gfs
        # Semaine 19 (mai 04-10) + semaine 20 (mai 11) — vérifiées ISO
        # 2026-05-04 est un lundi (début de semaine 19)
        # 2026-05-11 est un lundi (début de semaine 20)
        archives = [
            "a_20260504.tar", "a_20260505.tar", "a_20260506.tar",
            "a_20260507.tar", "a_20260508.tar", "a_20260509.tar",
            "a_20260510.tar", "a_20260511.tar",
        ]
        # daily=3 : mai11, mai10, mai09
        # weekly=2 : sem20→mai11, sem19→mai10 (déjà en daily)
        # monthly=1 : mai→mai11
        # Keepers : {mai09, mai10, mai11}
        # Supprimés : {mai04, mai05, mai06, mai07, mai08}
        to_delete = _retention_gfs(archives, {"daily": 3, "weekly": 2, "monthly": 1})
        assert "a_20260511.tar" not in to_delete
        assert "a_20260510.tar" not in to_delete
        assert "a_20260509.tar" not in to_delete
        assert "a_20260504.tar" in to_delete
        assert "a_20260508.tar" in to_delete
        assert len(to_delete) == 5

    def test_une_archive_peut_couvrir_plusieurs_niveaux(self):
        from retention import _retention_gfs
        # Une seule archive : elle doit être conservée même avec daily=1, weekly=1, monthly=1
        archives = ["a_20260511.tar"]
        assert _retention_gfs(archives, {"daily": 1, "weekly": 1, "monthly": 1}) == []

    def test_defaults_utilises_si_config_vide(self):
        from retention import _retention_gfs
        # Config vide → defaults daily=7, weekly=4, monthly=12
        # Avec 3 archives, tout doit être gardé
        archives = ["a_20260509.tar", "a_20260510.tar", "a_20260511.tar"]
        assert _retention_gfs(archives, {}) == []
