"""Tests for contacts migration from memory/contacts/ to contacts/."""

from __future__ import annotations

from pathlib import Path

from icarus.runtime.context import UserContext


class TestContactsMigration:
    def _make_ctx(self, tmp_path: Path) -> UserContext:
        config_dir = tmp_path / ".icarus"
        return UserContext(
            username="test",
            home_dir=tmp_path,
            working_dir=tmp_path,
            config_dir=config_dir,
        )

    def test_migrates_vcf_files(self, tmp_path: Path):
        """VCF files in memory/contacts/ should be moved to contacts/."""
        ctx = self._make_ctx(tmp_path)

        # Create old structure with contacts
        old_dir = ctx.memory_dir / "contacts"
        old_dir.mkdir(parents=True)
        (old_dir / "alice.vcf").write_text("BEGIN:VCARD\nFN:Alice\nEND:VCARD")
        (old_dir / "bob.vcf").write_text("BEGIN:VCARD\nFN:Bob\nEND:VCARD")

        ctx.ensure_dirs()

        # Contacts should now be in the new location
        assert (ctx.contacts_dir / "alice.vcf").exists()
        assert (ctx.contacts_dir / "bob.vcf").exists()

        # Old files should be gone (moved, not copied)
        assert not (old_dir / "alice.vcf").exists()
        assert not (old_dir / "bob.vcf").exists()

    def test_no_overwrite_on_migration(self, tmp_path: Path):
        """If a file already exists at destination, don't overwrite it."""
        ctx = self._make_ctx(tmp_path)

        # Create old structure
        old_dir = ctx.memory_dir / "contacts"
        old_dir.mkdir(parents=True)
        (old_dir / "alice.vcf").write_text("OLD ALICE")

        # Create new structure with existing file
        ctx.contacts_dir.mkdir(parents=True)
        (ctx.contacts_dir / "alice.vcf").write_text("NEW ALICE")

        ctx.ensure_dirs()

        # New version should be preserved
        assert (ctx.contacts_dir / "alice.vcf").read_text() == "NEW ALICE"
        # Old version should NOT be moved (destination existed)
        assert (old_dir / "alice.vcf").exists()

    def test_no_error_without_legacy_dir(self, tmp_path: Path):
        """Should not error if memory/contacts/ doesn't exist."""
        ctx = self._make_ctx(tmp_path)
        ctx.ensure_dirs()  # Should not raise

        assert ctx.contacts_dir.exists()
        assert ctx.calendar_dir.exists()
        assert ctx.todos_dir.exists()

    def test_creates_pim_directories(self, tmp_path: Path):
        """ensure_dirs should create contacts/, calendar/, todos/."""
        ctx = self._make_ctx(tmp_path)
        ctx.ensure_dirs()

        assert ctx.contacts_dir.exists()
        assert ctx.calendar_dir.exists()
        assert ctx.todos_dir.exists()

    def test_non_vcf_files_not_migrated(self, tmp_path: Path):
        """Non-.vcf files in memory/contacts/ should stay put."""
        ctx = self._make_ctx(tmp_path)

        old_dir = ctx.memory_dir / "contacts"
        old_dir.mkdir(parents=True)
        (old_dir / "notes.txt").write_text("some notes")
        (old_dir / "alice.vcf").write_text("BEGIN:VCARD\nFN:Alice\nEND:VCARD")

        ctx.ensure_dirs()

        # VCF migrated, txt stays
        assert (ctx.contacts_dir / "alice.vcf").exists()
        assert (old_dir / "notes.txt").exists()
        assert not (ctx.contacts_dir / "notes.txt").exists()

    def test_empty_old_dir_removed_after_migration(self, tmp_path: Path):
        """After migrating all .vcf files, memory/contacts/ should be removed."""
        ctx = self._make_ctx(tmp_path)

        old_dir = ctx.memory_dir / "contacts"
        old_dir.mkdir(parents=True)
        (old_dir / "alice.vcf").write_text("BEGIN:VCARD\nFN:Alice\nEND:VCARD")
        (old_dir / "bob.vcf").write_text("BEGIN:VCARD\nFN:Bob\nEND:VCARD")

        ctx.ensure_dirs()

        # Contacts migrated
        assert (ctx.contacts_dir / "alice.vcf").exists()
        assert (ctx.contacts_dir / "bob.vcf").exists()
        # Old directory should be gone
        assert not old_dir.exists()

    def test_non_empty_old_dir_preserved(self, tmp_path: Path):
        """If memory/contacts/ has non-.vcf files, it should be left alone."""
        ctx = self._make_ctx(tmp_path)

        old_dir = ctx.memory_dir / "contacts"
        old_dir.mkdir(parents=True)
        (old_dir / "alice.vcf").write_text("BEGIN:VCARD\nFN:Alice\nEND:VCARD")
        (old_dir / "notes.txt").write_text("important notes")

        ctx.ensure_dirs()

        # VCF migrated, but directory stays because notes.txt remains
        assert (ctx.contacts_dir / "alice.vcf").exists()
        assert old_dir.exists()
        assert (old_dir / "notes.txt").exists()

    def test_ensure_dirs_idempotent_after_migration(self, tmp_path: Path):
        """Second ensure_dirs() call should be idempotent after migration."""
        ctx = self._make_ctx(tmp_path)

        old_dir = ctx.memory_dir / "contacts"
        old_dir.mkdir(parents=True)
        (old_dir / "alice.vcf").write_text("BEGIN:VCARD\nFN:Alice\nEND:VCARD")

        ctx.ensure_dirs()

        # Old directory removed after first call
        assert not old_dir.exists()
        assert (ctx.contacts_dir / "alice.vcf").exists()

        # Second call should not raise (old_dir is gone, nothing to migrate)
        ctx.ensure_dirs()

        # Everything still intact
        assert (ctx.contacts_dir / "alice.vcf").exists()
        assert not old_dir.exists()
