import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';

import 'package:lanebow/screens/club/event_details_screen.dart';
import 'package:lanebow/models/event_model.dart';
import 'package:lanebow/models/participant_model.dart';
import 'package:lanebow/models/score_model.dart';
import 'package:lanebow/models/member_model.dart';
import 'package:lanebow/models/club_model.dart';
import 'package:lanebow/models/team_model.dart';
import 'package:lanebow/services/event_service.dart';
import 'package:lanebow/services/club_service.dart';
import 'package:lanebow/services/member_service.dart';
import 'package:lanebow/widgets/loading_indicator.dart';

// 간단한 테스트 더블 구현 (ChangeNotifier 유지)
class FakeEventService extends EventService {
  @override
  List<Participant> participants = [];
  @override
  List<Score> scores = [];

  @override
  Future<List<Participant>> fetchEventParticipants(String eventId) async {
    return participants;
  }

  @override
  Future<List<Score>> fetchEventScores(String eventId) async {
    return scores;
  }

  @override
  Future<List<Team>> fetchEventTeams(String eventId) async {
    // 팀 기능은 테스트에서 필수가 아니므로 빈 리스트를 즉시 반환하여 네트워크 의존성을 제거
    return [];
  }
}

class FakeClubService extends ClubService {
  Club? club;
  @override
  Future<Club> fetchClub(String clubId) async {
    return club ?? Club(name: '클럽', id: clubId);
  }
}

class FakeMemberService extends MemberService {
  List<Member> membersByIds = [];
  @override
  Future<List<Member>> fetchMembersByIds(String clubId, List<String> ids) async {
    return membersByIds;
  }

  @override
  Future<void> setClubId(String clubId) async {
    // no-op: 테스트에서는 내부 상태 주입만 필요하며 네트워크 호출 불필요
    return;
  }

  @override
  Future<void> fetchClubMembers() async {
    // no-op: 테스트에서는 네트워크 호출 없이 즉시 완료
    return;
  }
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  // ChangeNotifier 서브타입에 Provider.value 사용 허용(자동 업데이트 불필요한 테스트 시나리오)
  Provider.debugCheckInvalidValueType = null;

  group('EventDetailsScreen', () {
    late FakeEventService eventService;
    late FakeClubService clubService;
    late FakeMemberService memberService;

    final event = Event(
      id: 'e1',
      clubId: 'c1',
      title: '테스트 이벤트',
      description: '설명입니다',
      startDate: DateTime(2025, 1, 2, 19, 30),
      endDate: DateTime(2025, 1, 2, 22, 00),
      location: '강남볼링장',
      type: '정기전',
      status: '진행중',
      maxParticipants: 24,
      currentParticipants: 2,
      gameCount: 3,
      participantFee: 10000,
      registrationDeadline: DateTime(2024, 12, 31, 23, 59),
      publicHash: 'hash123',
      accessPassword: '1234',
      isActive: true,
    );

    setUp(() {
      eventService = FakeEventService();
      clubService = FakeClubService();
      memberService = FakeMemberService();

      // Participants
      eventService.participants = [
        Participant(
          id: 'p1',
          eventId: 'e1',
          memberId: 'm1',
          registeredAt: DateTime(2025, 1, 1),
        ),
        Participant(
          id: 'p2',
          eventId: 'e1',
          memberId: 'm2',
          registeredAt: DateTime(2025, 1, 1),
        ),
      ];
      // Scores
      eventService.scores = [
        Score(
          id: 's1',
          eventId: 'e1',
          memberId: 'm1',
          clubId: 'c1',
          frames: const [100, 100, 100, 100, 100],
          totalScore: 500,
          handicap: 0,
          date: DateTime(2025, 1, 2),
        ),
      ];
      // Club
      clubService.club = Club(id: 'c1', name: '볼링클럽', ownerId: 'u1');
      // Members
      memberService.membersByIds = [
        Member(
          id: 'm1',
          userId: 'u1',
          clubId: 'c1',
          name: '철수',
          email: 'a@b.com',
          isActive: true,
          gender: 'M',
          birthDate: DateTime(1990, 1, 1),
        ),
        Member(
          id: 'm2',
          userId: 'u2',
          clubId: 'c1',
          name: '영희',
          email: 'c@d.com',
          isActive: true,
          gender: 'F',
          birthDate: DateTime(1992, 1, 1),
        ),
      ];
    });

    Widget wrapWithProviders(Widget child) {
      return MultiProvider(
        providers: [
          Provider<EventService>.value(value: eventService),
          Provider<ClubService>.value(value: clubService),
          Provider<MemberService>.value(value: memberService),
        ],
        child: MaterialApp(home: child),
      );
    }

    testWidgets('로딩 후 기본 정보 탭 렌더링 및 핵심 정보 표시', (tester) async {
      await tester.pumpWidget(wrapWithProviders(EventDetailsScreen(event: event)));

      // 초기 로딩 표시
      expect(find.byType(LoadingIndicator), findsOneWidget);

      // async 로딩/초기 빌드가 끝나도록 약간 더 대기 (무한 대기 방지)
      await tester.pump(const Duration(milliseconds: 200));
      await tester.pump(const Duration(milliseconds: 200));

      // AppBar 제목
      expect(find.text('테스트 이벤트'), findsOneWidget);

      // 탭 존재 확인
      expect(find.text('기본 정보'), findsOneWidget);
      expect(find.text('참가자'), findsOneWidget);
      expect(find.text('점수'), findsOneWidget);
      expect(find.text('팀'), findsOneWidget);

      // 기본 정보 섹션이 렌더링되고 공유 버튼이 존재
      expect(find.byIcon(Icons.share), findsOneWidget);
      // 장소/날짜와 같은 텍스트 일부가 표시되는지(정확한 포맷 대신 포함 여부만 확인)
      expect(find.textContaining('강남'), findsWidgets);
    });

    testWidgets('참가자 탭: 참가자 수와 리스트 표시', (tester) async {
      await tester.pumpWidget(wrapWithProviders(EventDetailsScreen(event: event)));
      await tester.pump(const Duration(milliseconds: 50));
      await tester.pump(const Duration(milliseconds: 50));

      // 참가자 탭으로 이동: 탭 터치 대신 TabBarView를 드래그로 넘김(제스처 경로 단순화)
      await tester.drag(find.byType(TabBarView), const Offset(-400, 0));
      await tester.pump(const Duration(milliseconds: 250));
      await tester.pump(const Duration(milliseconds: 250));

      // 리스트가 렌더링되는지(정확한 항목 텍스트 대신 리스트 존재 확인)
      expect(find.byType(ListView), findsWidgets);
    });
  });
}
