#!/usr/bin/env python3
"""Tests for session backup module."""

import json
import os
import sys
import tempfile
import unittest
from pathlib import Path

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from tools.session_backup import SessionBackup


class TestSessionBackup(unittest.TestCase):
    def setUp(self):
        self.tmp_home = tempfile.mkdtemp()
        self.tmp_backup = tempfile.mkdtemp()

        # Create fake home structure
        home = Path(self.tmp_home)
        (home / "memories").mkdir()
        (home / "sessions").mkdir()
        (home / "cron").mkdir()

        (home / "config.yaml").write_text("model: test\n")
        (home / "memories" / "MEMORY.md").write_text("# Memory\nTest entry\n")
        (home / "memories" / "USER.md").write_text("# User\nTest user\n")
        (home / "channel_directory.json").write_text("{}")
        (home / "cron" / "jobs.json").write_text("[]")
        (home / "sessions" / "sessions.json").write_text("[]")
        (home / "sessions" / "session_test1.json").write_text('{"id": "test1"}')
        (home / "sessions" / "session_test2.json").write_text('{"id": "test2"}')

        self.backup = SessionBackup(
            home_dir=self.tmp_home,
            backup_dir=self.tmp_backup,
            max_backups=3,
        )

    def tearDown(self):
        import shutil
        shutil.rmtree(self.tmp_home, ignore_errors=True)
        shutil.rmtree(self.tmp_backup, ignore_errors=True)

    def test_create_backup(self):
        result = self.backup.create_backup("test")
        self.assertIn("filename", result)
        self.assertIn("test", result["filename"])
        self.assertGreater(result["files_included"], 0)
        self.assertTrue(Path(result["path"]).exists())

    def test_create_backup_includes_critical_files(self):
        result = self.backup.create_backup("test")
        # state.db and gateway_state.json don't exist in test fixture
        self.assertGreater(result["files_included"], 3)

    def test_list_backups(self):
        self.backup.create_backup("first")
        self.backup.create_backup("second")
        backups = self.backup.list_backups()
        self.assertEqual(len(backups), 2)
        self.assertIn("filename", backups[0])
        self.assertIn("size", backups[0])

    def test_list_backups_empty(self):
        backups = self.backup.list_backups()
        self.assertEqual(len(backups), 0)

    def test_rotation(self):
        for i in range(5):
            self.backup.create_backup(f"rot{i}")
        backups = self.backup.list_backups()
        self.assertLessEqual(len(backups), 3)  # max_backups=3

    def test_restore_dry_run(self):
        self.backup.create_backup("restore-test")
        backups = self.backup.list_backups()
        result = self.backup.restore_backup(backups[0]["filename"], dry_run=True)
        self.assertEqual(result["mode"], "dry_run")
        self.assertGreater(result["total_files"], 0)

    def test_restore_not_found(self):
        result = self.backup.restore_backup("nonexistent.tar.gz")
        self.assertIn("error", result)

    def test_check_freshness_no_backups(self):
        result = self.backup.check_freshness()
        self.assertFalse(result["fresh"])
        self.assertIn("No backups", result["reason"])

    def test_check_freshness_fresh(self):
        self.backup.create_backup("fresh")
        result = self.backup.check_freshness()
        self.assertTrue(result["fresh"])
        self.assertLess(result["age_hours"], 1)

    def test_human_size(self):
        self.assertEqual(SessionBackup._human_size(500), "500.0B")
        self.assertEqual(SessionBackup._human_size(1024), "1.0KB")
        self.assertEqual(SessionBackup._human_size(1048576), "1.0MB")

    def test_missing_files_reported(self):
        result = self.backup.create_backup("missing")
        # state.db doesn't exist in test fixture
        self.assertIn("state.db", result["files_missing"])


if __name__ == "__main__":
    unittest.main()
