import socket
import types
from target_simulator.core.sfp_transport import SfpTransport
from target_simulator.core.sfp_structures import SFPHeader


class DummySocket:
    def __init__(self):
        self.sent = []

    def sendto(self, data, addr):
        self.sent.append((bytes(data), addr))

    def recvfrom(self, n):
        raise socket.timeout()


def make_header(flow=ord('M')):
    hdr = bytearray(SFPHeader.size())
    # naive offsets based on structure helper
    hdr[SFPHeader.get_field_offset('SFP_FLOW')] = flow
    hdr[SFPHeader.get_field_offset('SFP_TID')] = 1
    hdr[SFPHeader.get_field_offset('SFP_FLAGS')] = 0
    # set totals to minimal valid values
    hdr[SFPHeader.get_field_offset('SFP_TOTFRGAS')] = 1
    hdr[SFPHeader.get_field_offset('SFP_TOTSIZE')] = 4
    hdr[SFPHeader.get_field_offset('SFP_PLSIZE')] = 4
    hdr[SFPHeader.get_field_offset('SFP_PLOFFSET')] = 0
    return bytes(hdr)


def test_send_ack_uses_ack_config(monkeypatch):
    sent = []
    s = SfpTransport('127.0.0.1', 0, {}, ack_config={ord('M'): 99})
    s._socket = DummySocket()
    header = make_header()
    s._send_ack(('1.2.3.4', 10000), header)
    assert s._socket.sent
    data, addr = s._socket.sent[0]
    # WIN field should be set to 99
    assert data[SFPHeader.get_field_offset('SFP_WIN')] == 99


def test_process_single_fragment_calls_handler(monkeypatch):
    called = {}

    def handler(payload):
        called['ok'] = True

    header = bytearray(make_header())
    payload = b'abcd'
    raw = bytes(header) + payload

    s = SfpTransport('127.0.0.1', 0, {ord('M'): handler})
    # Put internal buffers as if socket gave us the packet
    s._process_packet(raw, ('127.0.0.1', 1000))
    assert called.get('ok')
