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

import 'package:lanebow/services/event_service.dart';
import 'package:lanebow/services/api_service.dart';
import 'package:lanebow/config/api_config.dart';
import 'package:lanebow/models/participant_model.dart';

void main() {
  group('EventService participants API contract', () {
    late ApiService api;
    late Dio dio;
    late List<RequestOptions> captured;

    setUp(() async {
      SharedPreferences.setMockInitialValues({
        ApiConfig.userIdKey: 'user-1',
        ApiConfig.clubIdKey: 'club-1',
      });

      api = ApiService();
      dio = Dio(BaseOptions(baseUrl: ApiConfig.baseUrl));
      captured = [];

      dio.interceptors.add(InterceptorsWrapper(
        onRequest: (options, handler) {
          captured.add(options);
          // 라우트 분기
          if (options.path.endsWith('/events/evt-1/participants/list')) {
            // participants: 배열로 응답
            return handler.resolve(Response(
              requestOptions: options,
              statusCode: 200,
              data: [
                {
                  'id': 'p1',
                  'eventId': 'evt-1',
                  'memberId': 'm1',
                  'status': 'confirmed',
                  'paymentStatus': 'paid',
                  'Member': {
                    'name': '홍길동',
                    'email': 'hong@example.com',
                    'phone': '010-1111-2222',
                  }
                }
              ],
            ));
          }
          if (options.path.endsWith('/events/evt-1/participants')) {
            final req = options.data as Map<String, dynamic>? ?? {};
            return handler.resolve(Response(
              requestOptions: options,
              statusCode: 200,
              data: {
                'participant': {
                  'id': 'new-1',
                  'eventId': req['eventId'] ?? 'evt-1',
                  'memberId': 'mX',
                  'name': req['name'],
                  'status': req['status'],
                  'paymentStatus': req['paymentStatus'] ?? (req['isPaid'] == true ? 'paid' : 'unpaid'),
                }
              },
            ));
          }
          if (options.path.endsWith('/events/evt-1/participants/p1')) {
            final req = options.data as Map<String, dynamic>? ?? {};
            return handler.resolve(Response(
              requestOptions: options,
              statusCode: 200,
              data: {
                'participant': {
                  'id': 'p1',
                  'eventId': 'evt-1',
                  'memberId': 'm1',
                  'name': req['name'] ?? '홍길동',
                  'status': req['status'] ?? 'confirmed',
                  'paymentStatus': req['paymentStatus'] ?? 'paid',
                }
              },
            ));
          }

          // 기본: 404
          return handler.resolve(Response(
            requestOptions: options,
            statusCode: 404,
            data: {'error': 'not found', 'path': options.path},
          ));
        },
      ));

      api.setDio(dio);
      api.setToken('test-token');
    });

    test('fetchEventParticipants posts to list endpoint with clubId/userId and parses participants', () async {
      final svc = EventService.forTest(api);
      // 내부 상태에 clubId 세팅
      svc.setClubId('club-1');
      await svc.initialize('test-token');

      final list = await svc.fetchEventParticipants('evt-1');

      // 요청 검증
      expect(captured.isNotEmpty, true);
      final req = captured.first;
      expect(req.method, 'POST');
      expect(req.path, '${ApiConfig.clubs}/events/evt-1/participants/list');
      final body = req.data as Map<String, dynamic>;
      expect(body['clubId'], 'club-1');
      expect(body['userId'], 'user-1');
      expect(body['eventId'], 'evt-1');

      // 파싱 검증
      expect(list, isA<List<Participant>>());
      expect(list.length, 1);
      final p = list.first;
      expect(p.name, '홍길동');
      expect(p.email, 'hong@example.com');
      expect(p.phoneNumber, '010-1111-2222');
      expect(p.status, 'confirmed');
      expect(p.isPaid, isTrue);
    });

    test('addParticipant posts to correct endpoint and merges clubId into payload', () async {
      final svc = EventService.forTest(api);
      svc.setClubId('club-1');
      await svc.initialize('test-token');

      final created = await svc.addParticipant('evt-1', {
        'eventId': 'evt-1',
        'name': '새 참가자',
        'status': 'registered',
        'isPaid': false,
        'paymentStatus': 'unpaid',
      });

      // 마지막 요청 검증
      final req = captured.last;
      expect(req.method, 'POST');
      expect(req.path, '${ApiConfig.clubs}/events/evt-1/participants');
      final body = req.data as Map<String, dynamic>;
      expect(body['clubId'], 'club-1');
      expect(body['name'], '새 참가자');
      expect(body['status'], 'registered');
      expect(body['paymentStatus'], 'unpaid');

      expect(created.id, 'new-1');
      expect(created.status, 'registered');
      expect(created.isPaid, isFalse);
    });

    test('updateParticipant puts to correct endpoint and returns updated model', () async {
      final svc = EventService.forTest(api);
      svc.setClubId('club-1');
      await svc.initialize('test-token');

      final updated = await svc.updateParticipant('evt-1', 'p1', {
        'name': '수정된',
        'status': 'confirmed',
        'paymentStatus': 'paid',
      });

      final req = captured.last;
      expect(req.method, 'PUT');
      expect(req.path, '${ApiConfig.clubs}/events/evt-1/participants/p1');
      final body = req.data as Map<String, dynamic>;
      expect(body['name'], '수정된');
      expect(body['status'], 'confirmed');
      expect(body['paymentStatus'], 'paid');

      expect(updated.id, 'p1');
      expect(updated.name, '수정된');
      expect(updated.status, 'confirmed');
      expect(updated.isPaid, isTrue);
    });
  });
}
