"""Tests for :func:`mgf.vm.forensics.archive.archive_case` (Phase 17, FN-Chunk-B3)."""

from __future__ import annotations

import tarfile
from datetime import UTC, datetime
from typing import TYPE_CHECKING
from uuid import uuid4

import pytest
from mgf.vm.core.exceptions import OperationError

from mgf.vm.forensics.archive import archive_case
from mgf.vm.forensics.case import Case, CaseStatus
from mgf.vm.forensics.store import CaseStore

if TYPE_CHECKING:
    from pathlib import Path


def _make_case(name: str = "alpha") -> Case:
    return Case(
        name=name,
        case_id=uuid4(),
        vm_name="suspect-1",
        status=CaseStatus.PREPARING,
        created_at=datetime(2026, 4, 26, 12, 0, tzinfo=UTC),
    )


@pytest.fixture
def store(tmp_path: Path) -> CaseStore:
    return CaseStore(root=tmp_path / "forensics")


# ---------------------------------------------------------------------------
# Happy path
# ---------------------------------------------------------------------------


class TestArchiveCase:
    def test_creates_targz_with_case_dir_inside(
        self,
        store: CaseStore,
        tmp_path: Path,
    ) -> None:
        store.create(_make_case("alpha"))
        target = tmp_path / "alpha.tar.gz"

        result = archive_case(store, "alpha", target)

        assert result == target
        assert target.exists()
        with tarfile.open(target, "r:gz") as tar:
            names = tar.getnames()
        # The arcname puts every entry under "alpha/".
        assert any(n.startswith("alpha/") for n in names)
        assert any(n.endswith("case.yaml") for n in names)

    def test_transitions_to_archived(
        self,
        store: CaseStore,
        tmp_path: Path,
    ) -> None:
        store.create(_make_case("alpha"))
        archive_case(store, "alpha", tmp_path / "out.tar.gz")
        case = store.load("alpha")
        assert case.status is CaseStatus.ARCHIVED

    def test_refuses_to_overwrite_existing_target(
        self,
        store: CaseStore,
        tmp_path: Path,
    ) -> None:
        store.create(_make_case("alpha"))
        target = tmp_path / "out.tar.gz"
        target.write_bytes(b"")
        with pytest.raises(OperationError, match="refusing to overwrite"):
            archive_case(store, "alpha", target)

    def test_refresh_manifest_default_writes_manifest(
        self,
        store: CaseStore,
        tmp_path: Path,
    ) -> None:
        store.create(_make_case("alpha"))
        case_dir = store.case_dir("alpha")
        manifest = case_dir / "manifest.json"
        if manifest.exists():
            manifest.unlink()
        archive_case(store, "alpha", tmp_path / "out.tar.gz")
        # Manifest re-written before tarring.
        assert manifest.exists()

    def test_refresh_manifest_disabled_skips_rewrite(
        self,
        store: CaseStore,
        tmp_path: Path,
    ) -> None:
        store.create(_make_case("alpha"))
        case_dir = store.case_dir("alpha")
        manifest = case_dir / "manifest.json"
        if manifest.exists():
            manifest.unlink()
        archive_case(store, "alpha", tmp_path / "out.tar.gz", refresh_manifest=False)
        assert not manifest.exists()

    def test_archived_case_yaml_carries_archived_status(
        self,
        store: CaseStore,
        tmp_path: Path,
    ) -> None:
        # The archived tar.gz should contain case.yaml with
        # `status: archived` — proves the transition runs BEFORE
        # the tar create call.
        store.create(_make_case("alpha"))
        target = tmp_path / "out.tar.gz"
        archive_case(store, "alpha", target)
        with tarfile.open(target, "r:gz") as tar:
            member = tar.getmember("alpha/case.yaml")
            extracted = tar.extractfile(member)
            assert extracted is not None
            content = extracted.read().decode("utf-8")
        assert "status: archived" in content

    def test_unknown_case_raises(self, store: CaseStore, tmp_path: Path) -> None:
        with pytest.raises(OperationError):
            archive_case(store, "no-such-case", tmp_path / "out.tar.gz")
