import json
import tempfile
import unittest
from pathlib import Path

from scripts.package_firmware import build_manifest, extract_firmware_version, package_bundle


class PackageFirmwareTests(unittest.TestCase):
    def test_extract_firmware_version_reads_init_string(self):
        header_text = '#define initSting "EBBv13_and_above Protocol emulated by Eggduino-Firmware V1.6a"\n'

        self.assertEqual(extract_firmware_version(header_text), "1.6a")

    def test_build_manifest_matches_expected_esp32_offsets(self):
        manifest = build_manifest("1.6a")

        self.assertEqual(manifest["name"], "EggDuino ESP32 Firmware")
        self.assertEqual(manifest["version"], "1.6a")
        self.assertTrue(manifest["new_install_prompt_erase"])
        self.assertEqual(manifest["builds"][0]["chipFamily"], "ESP32")
        self.assertEqual(
            manifest["builds"][0]["parts"],
            [
                {"path": "bootloader.bin", "offset": 4096},
                {"path": "partitions.bin", "offset": 32768},
                {"path": "boot_app0.bin", "offset": 57344},
                {"path": "firmware.bin", "offset": 65536},
            ],
        )

    def test_package_bundle_copies_outputs_and_removes_stale_files(self):
        with tempfile.TemporaryDirectory() as temp_dir:
            temp_path = Path(temp_dir)
            build_dir = temp_path / "build"
            build_dir.mkdir()
            header_path = temp_path / "EggDuino.h"
            output_dir = temp_path / "firmware"
            output_dir.mkdir()
            boot_app0_path = temp_path / "boot_app0.bin"

            build_artifacts = {
                "bootloader.bin": "bootloader",
                "partitions.bin": "partitions",
                "firmware.bin": "firmware-bin",
                "firmware.elf": "firmware-elf",
                "firmware.map": "firmware-map",
            }
            for file_name, contents in build_artifacts.items():
                (build_dir / file_name).write_text(contents, encoding="utf-8")

            header_path.write_text(
                '#define initSting "EBBv13_and_above Protocol emulated by Eggduino-Firmware V1.6b"\n',
                encoding="utf-8",
            )
            boot_app0_path.write_text("boot-app0", encoding="utf-8")
            (output_dir / "stale.txt").write_text("old", encoding="utf-8")

            package_bundle(
                build_dir=build_dir,
                boot_app0_path=boot_app0_path,
                header_path=header_path,
                output_dir=output_dir,
            )

            self.assertFalse((output_dir / "stale.txt").exists())
            expected_files = {
                "bootloader.bin": "bootloader",
                "partitions.bin": "partitions",
                "firmware.bin": "firmware-bin",
                "firmware.elf": "firmware-elf",
                "firmware.map": "firmware-map",
                "boot_app0.bin": "boot-app0",
            }
            for file_name, contents in expected_files.items():
                self.assertEqual((output_dir / file_name).read_text(encoding="utf-8"), contents)

            manifest = json.loads((output_dir / "manifest.json").read_text(encoding="utf-8"))
            self.assertEqual(manifest["version"], "1.6b")


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