import 'package:flutter_test/flutter_test.dart';
import 'package:dio/dio.dart';

import 'package:lanebow/services/event_service.dart';
import 'package:lanebow/services/api_service.dart';

class _InterceptPutPost extends Interceptor {
  RequestOptions? lastPutOptions;
  dynamic lastPutData;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // Mock responses for addParticipant (POST) and updateParticipant (PUT)
    if (options.method == 'POST' && options.path.endsWith('/participants')) {
      handler.resolve(Response(
        requestOptions: options,
        statusCode: 201,
        data: {
          'message': '참가자가 등록되었습니다.',
          'participant': {
            'id': '99',
            'eventId': options.path.split('/').reversed.skip(1).first,
            'memberId': (options.data is Map && options.data['memberId'] != null)
                ? options.data['memberId'].toString()
                : '7',
            'status': 'confirmed',
            'paymentStatus': 'unpaid',
          }
        },
      ));
      return;
    }
    if (options.method == 'PUT' && options.path.endsWith('/participants')) {
      lastPutOptions = options;
      lastPutData = options.data;
      handler.resolve(Response(
        requestOptions: options,
        statusCode: 200,
        data: {
          'message': '참가자 정보가 수정되었습니다.',
          'participant': {
            'id': (options.data is Map) ? options.data['id']?.toString() : '99',
            'eventId': options.path.split('/').reversed.skip(1).first,
            'memberId': (options.data is Map) ? options.data['memberId']?.toString() : '7',
            'status': (options.data is Map) ? options.data['status'] ?? 'pending' : 'pending',
            'paymentStatus': ((options.data is Map) ? options.data['paymentStatus'] : null) ?? 'unpaid',
          }
        },
      ));
      return;
    }

    // Default pass-through success
    handler.resolve(Response(requestOptions: options, statusCode: 200, data: {}));
  }
}

void main() {
  group('EventService.updateParticipant', () {
    test('auto-fills missing memberId from local cache when updating', () async {
      // Arrange
      final api = ApiService();
      final dio = Dio(BaseOptions(baseUrl: ''));
      final tap = _InterceptPutPost();
      dio.interceptors.add(tap);
      api.setDio(dio);

      final service = EventService.forTest(api);
      await service.initialize('dummy-token');
      service.setClubId('3');

      // Seed local cache by adding a participant (memberId = 7)
      await service.addParticipant('1', {
        'memberId': '7',
        'status': 'confirmed',
        'paymentStatus': 'unpaid',
      });

      // Act: update without providing memberId
      await service.updateParticipant('1', '99', {
        'status': 'canceled',
      });

      // Assert: PUT called with memberId auto-filled
      expect(tap.lastPutOptions, isNotNull);
      expect(tap.lastPutOptions!.method, equals('PUT'));
      expect(tap.lastPutOptions!.path, equals('/club/events/1/participants'));
      expect(tap.lastPutData, isA<Map>());
      expect(tap.lastPutData['memberId']?.toString(), equals('7'));
      expect(tap.lastPutData['status'], equals('canceled'));
      expect(tap.lastPutData['clubId']?.toString(), equals('3'));
    });
  });
}
