from __future__ import annotations

from contextlib import contextmanager
from pathlib import Path
from types import SimpleNamespace

from asm3042_flasher import cli
from asm3042_flasher.device import DeviceInfo


def test_permanent_write_internal_continues_when_mailbox_version_is_unavailable(
    monkeypatch,
    tmp_path: Path,
    capsys,
) -> None:
    firmware_path = tmp_path / "fw.bin"
    firmware_path.write_bytes(b"\x00\x00")

    info = DeviceInfo(
        bdf="0000:01:00.0",
        vendor_id=0x1B21,
        device_id=0x3142,
        class_code=0x0C0330,
        driver=None,
        sysfs_path=tmp_path,
    )
    rom = SimpleNamespace(
        manufacturer="WinBond",
        model="W25X10",
        manufacturer_id=0xEF,
        memory_type_id=0x30,
        capacity_id=0x11,
        flash_size_bytes=0x20000,
        sector_size_bytes=0x1000,
    )
    permanent_image = SimpleNamespace(family_tag="2214A", raw_size=98304)

    class FakeController:
        def __init__(self, controller_info):
            self.info = controller_info

        def __enter__(self):
            return self

        def __exit__(self, exc_type, exc, tb):
            return None

        @contextmanager
        def temporarily_unbound(self, enabled: bool = True):
            yield

        def get_firmware_version(self) -> int:
            raise TimeoutError("mailbox unavailable")

    monkeypatch.setattr(cli, "pick_device", lambda bdf: info)
    monkeypatch.setattr(cli, "ensure_protocol_supported", lambda info, force: None)
    monkeypatch.setattr(cli, "AsmediaXhciController", FakeController)
    monkeypatch.setattr(
        cli,
        "FirmwareImage",
        SimpleNamespace(from_path=lambda path: SimpleNamespace(
            source=str(path),
            size=131072,
            header_tags=("2214A_RCFG", "2214A_FW"),
        )),
    )
    monkeypatch.setattr(cli, "extract_permanent_firmware", lambda image: permanent_image)
    monkeypatch.setattr(cli, "read_internal_flash", lambda controller: (rom, b"\xAA" * 16))
    monkeypatch.setattr(cli, "write_internal_flash", lambda controller, firmware, verify: rom)

    result = cli._cmd_permanent_write_internal(
        str(firmware_path),
        bdf="0000:01:00.0",
        force_device=False,
        keep_driver_bound=False,
        backup_file=None,
        skip_backup=False,
        overwrite_backup=True,
        verify=True,
    )

    output = capsys.readouterr().out

    assert result == 0
    assert "firmware-running-before: unavailable" in output
    assert "status: internal-permanent-write-complete" in output
    assert (tmp_path / "fw.backup.bin").read_bytes() == (b"\xAA" * 16)
