import os
import json
import tempfile
from pathlib import Path

import pytest

from target_simulator.gui import sfp_debug_window
from target_simulator.core import sfp_structures


def make_sample_header(flow=1, seq=42, flags=0x05, payload_len=16):
    # Build a raw header using SFPHeader helpers if available, otherwise craft bytes
    hdr = sfp_structures.SFPHeader()
    hdr.flow = flow
    hdr.seq = seq
    hdr.flags = flags
    hdr.len = payload_len
    # ctypes struct -> bytes
    return bytes(hdr)


def test_flag_decoding_and_display():
    w = sfp_debug_window.SfpDebugWindow(master=None)

    # Build a header with known flags bits; call the display function
    raw = make_sample_header(flow=2, seq=7, flags=0x0A, payload_len=8)
    # append some body bytes so hex dump shows up
    raw_full = raw + b"\x01\x02\x03\x04"

    # call the public method to render into the widget buffer
    w._display_raw_packet(raw_full, ("127.0.0.1", 12345))

    # Inspect the underlying text buffer stored by the DummyWidget
    buf = w.raw_tab_text.get("1.0", "end")
    assert "SFP Header" in buf or "Failed to format raw packet" not in buf
    assert "SFP_FLAGS" in buf or "Flags legend" in buf


def test_history_buffer_and_persistence(tmp_path):
    router = sfp_debug_window.DebugPayloadRouter()
    # set history size to small value
    router.set_history_size(3)
    # push 4 raw packets; oldest should be dropped when history maxlen is 3
    for i in range(4):
        raw = make_sample_header(flow=1, seq=i, flags=0, payload_len=4) + b'abcd'
        router.update_raw_packet(raw, ("127.0.0.1", 1000 + i))

    hist = router.get_history()
    assert len(hist) == 3

    # test persistence toggle writes files (binary .bin as implemented)
    persist_dir = tmp_path / 'persist'
    router._persist_dir = str(persist_dir)
    persist_dir.mkdir(parents=True, exist_ok=True)
    router.set_persist(True)

    # add an entry that should be persisted
    router.update_raw_packet(b"HELLO", ("1.2.3.4", 5000))

    # persistence happens synchronously in update_raw_packet; check files
    files = list(persist_dir.glob('*.bin'))
    assert files, "persistence did not create any bin files"


def test_resize_image_fallback(monkeypatch):
    # Create a dummy PIL Image-like object if PIL not available
    class DummyImg:
        size = (100, 80)

        def resize(self, size, resample=None):
            return self

    w = sfp_debug_window.SfpDebugWindow(master=None)
    # Monkeypatch to ensure label widget dimensions are provided
    label = type('L', (), {})()
    label.winfo_width = lambda: 50
    label.winfo_height = lambda: 50

    img = DummyImg()
    out = w._resize_pil_to_label(img, label)
    # should return an image-like object (here the same instance)
    assert out is img
