from __future__ import annotations

import io
import tarfile
from pathlib import Path

import pytest

import k1link.device_plugins.xgrids_k1.firmware_credential as firmware_credential

FIXTURE_SECRET = b"fixture-only-network-secret"


def _tar_gz_member(name: str, payload: bytes) -> bytes:
    output = io.BytesIO()
    with tarfile.open(fileobj=output, mode="w:gz") as archive:
        member = tarfile.TarInfo(name)
        member.size = len(payload)
        archive.addfile(member, io.BytesIO(payload))
    return output.getvalue()


def test_exact_official_archive_extracts_one_bounded_declaration(
    monkeypatch: pytest.MonkeyPatch,
    tmp_path: Path,
) -> None:
    prefix = b"synthetic-rk-prefix"
    apps = (
        b"\x00" * 17
        + firmware_credential._AP_PSK_DECLARATION
        + FIXTURE_SECRET
        + b"\n"
        + b"\x00" * 31
    )
    image = prefix + apps
    upgrade = _tar_gz_member(firmware_credential.K1_FW302_RK_IMAGE_MEMBER, image)
    outer = _tar_gz_member(firmware_credential.K1_FW302_OUTER_MEMBER, upgrade)
    archive_path = tmp_path / "official-fw.tar"
    archive_path.write_bytes(outer)

    monkeypatch.setattr(firmware_credential, "K1_FW302_APPS_OFFSET", len(prefix))
    monkeypatch.setattr(firmware_credential, "K1_FW302_APPS_SIZE", len(apps))
    monkeypatch.setattr(
        firmware_credential,
        "_sha256",
        lambda _path: firmware_credential.K1_FW302_OFFICIAL_ARCHIVE_SHA256,
    )

    secret, digest = firmware_credential.extract_k1_fw302_ap_credential(archive_path)
    try:
        assert secret.reveal_ascii() == FIXTURE_SECRET.decode("ascii")
        assert FIXTURE_SECRET.decode("ascii") not in repr(secret)
        assert digest == firmware_credential.K1_FW302_OFFICIAL_ARCHIVE_SHA256
    finally:
        secret.zeroize()


def test_archive_hash_mismatch_stops_before_unpack(
    monkeypatch: pytest.MonkeyPatch,
    tmp_path: Path,
) -> None:
    archive_path = tmp_path / "wrong-fw.tar"
    archive_path.write_bytes(b"not-reviewed")
    monkeypatch.setattr(firmware_credential, "_sha256", lambda _path: "0" * 64)

    with pytest.raises(
        firmware_credential.FirmwareCredentialError,
        match="SHA-256",
    ):
        firmware_credential.extract_k1_fw302_ap_credential(archive_path)


def test_duplicate_declarations_fail_closed_without_exposing_values() -> None:
    payload = b"\n".join(
        [
            firmware_credential._AP_PSK_DECLARATION + FIXTURE_SECRET,
            firmware_credential._AP_PSK_DECLARATION + b"second-fixture-secret",
        ]
    ) + b"\n"

    with pytest.raises(
        firmware_credential.FirmwareCredentialError,
        match="not unique",
    ) as raised:
        firmware_credential._credential_from_chunks(iter([payload]))

    assert FIXTURE_SECRET.decode("ascii") not in str(raised.value)
