import json
import tempfile
import unittest
from pathlib import Path

from h8536.emulator.eeprom_image import build_eeprom_snapshot, format_eeprom_snapshot, write_eeprom_snapshot
from h8536.emulator.memory import MemoryMap
from h8536.emulator.peripherals.x24164 import X24164_LOGICAL_SIZE


def rom_bytes() -> bytes:
    rom = bytearray([0xFF] * 0xCB00)
    rom[0xC564 : 0xC564 + 0x400] = b"\x00" * 0x400
    rom[0xC564 + 0x18 * 2 : 0xC564 + 0x18 * 2 + 2] = b"\x60\x10"
    rom[0xC964 : 0xC964 + 0x100] = b"\x00" * 0x100
    rom[0xC966:0xC968] = b"\x6B\x6F"
    rom[0xC974:0xC976] = b"\x80\x00"
    return bytes(rom)


class EmulatorEepromImageTest(unittest.TestCase):
    def test_load_dump_and_write_log_cover_full_logical_image(self):
        memory = MemoryMap(rom_bytes())
        image = bytes([index & 0xFF for index in range(X24164_LOGICAL_SIZE)])

        memory.load_eeprom_image(image)
        self.assertEqual(memory.dump_eeprom_image(), image)
        self.assertEqual(memory.external[0xF400], 0x00)
        self.assertEqual(memory.external[0xF402], 0x02)

        self.assertTrue(memory.p9_bus.fast_write_word(0x0810, 0x1234))

        self.assertEqual(memory.p9_bus.fast_read_word(0x0810), (True, 0x1234))
        self.assertEqual(len(memory.p9_bus.x24164_bus.write_events), 2)
        self.assertIn("addr=810", memory.p9_bus.x24164_bus.write_log_lines()[-2])

    def test_snapshot_reports_records_factory_diffs_and_mapped_writes(self):
        memory = MemoryMap(rom_bytes())
        memory.seed_factory_eeprom_and_shadow()
        memory.p9_bus.fast_write_word(0x0110, 0x1234)

        report = build_eeprom_snapshot(memory, rom_bytes=rom_bytes())
        text = format_eeprom_snapshot(report)

        self.assertEqual(report["summary"]["write_word_count"], 1)
        self.assertEqual(report["write_word_events"][0]["new_word_hex"], "0x1234")
        self.assertEqual(report["write_word_events"][0]["mapped_selectors_hex"], ["0x018"])
        self.assertEqual(report["factory_diffs"][0]["address_hex"], "0x110")
        self.assertIn("EEPROM Word Writes", text)
        self.assertIn("selector", text)

    def test_write_snapshot_json(self):
        memory = MemoryMap(rom_bytes())
        memory.seed_factory_eeprom_and_shadow()

        with tempfile.TemporaryDirectory() as tmp:
            output = Path(tmp) / "eeprom.json"
            write_eeprom_snapshot(memory, output, rom_bytes=rom_bytes(), as_json=True, include_image_hex=True)

            payload = json.loads(output.read_text(encoding="utf-8"))
            self.assertEqual(payload["kind"], "emulator_eeprom_snapshot")
            self.assertEqual(len(payload["image_hex"]), X24164_LOGICAL_SIZE * 2)


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