from src.gameplay import recorder, smartResume


def _items():
    return [
        {'label': 'Start', 'coordinate': [100, 100, 7], 'type': 'walk', 'options': {}},
        {'label': '', 'coordinate': [150, 100, 7], 'type': 'walk', 'options': {}},
        {'label': 'Hunt', 'coordinate': [100, 150, 8], 'type': 'walk', 'options': {}},
    ]


def _context(coordinate):
    return {
        'ng_radar': {
            'coordinate': list(coordinate) if coordinate is not None else None,
        },
        'ng_cave': {'waypoints': {
            'items': _items(), 'currentIndex': 0, 'state': None,
        }},
    }


def test_nearest_waypoint_wins():
    assert smartResume.nearestWaypointIndex(_items(), (148, 101, 7)) == 1
    assert smartResume.nearestWaypointIndex(_items(), (99, 140, 8)) == 2
    assert smartResume.nearestWaypointIndex(_items(), (100, 100, 7)) == 0


def test_floor_difference_is_penalized():
    # x/y wie Index 1, aber eine Etage daneben → Start bleibt naeher
    assert smartResume.nearestWaypointIndex(_items(), (150, 100, 8)) == 1
    assert smartResume.nearestWaypointIndex(_items(), (110, 100, 8)) == 0


def test_resume_sets_index_and_logs(mocker):
    logSpy = mocker.patch.object(smartResume, 'logEvent')
    context = _context((148, 101, 7))

    smartResume.resumeAtNearestWaypoint(context)

    waypoints = context['ng_cave']['waypoints']
    assert waypoints['currentIndex'] == 1
    assert waypoints['state'] is None
    assert logSpy.call_args[0][0] == 'smartResume'


def test_resume_without_coordinate_is_noop(mocker):
    mocker.patch.object(smartResume, 'logEvent')
    context = _context(None)

    smartResume.resumeAtNearestWaypoint(context)

    assert context['ng_cave']['waypoints']['currentIndex'] == 0


def test_record_tick_collects_points():
    context = {'ng_recording': {}, 'ng_radar': {'coordinate': [100, 100, 7]}}

    recorder.recordTick(context)
    recorder.recordTick(context)  # gleiche Position → nicht doppelt
    context['ng_radar']['coordinate'] = [101, 100, 7]
    recorder.recordTick(context)

    assert context['ng_recording']['points'] == [[100, 100, 7], [101, 100, 7]]


def test_recording_off_is_noop():
    context = {'ng_radar': {'coordinate': [100, 100, 7]}}

    recorder.recordTick(context)

    assert 'ng_recording' not in context


def test_finish_adds_floor_transitions():
    recording = {'points': [
        [100, 100, 7], [100, 101, 8], [100, 102, 8], [100, 101, 7],
    ]}

    waypoints = recorder.finishRecording(recording)

    types = [waypoint['type'] for waypoint in waypoints]
    assert types == ['walk', 'moveDown', 'walk', 'walk', 'moveUp', 'walk']
