import 'package:bloc_test/bloc_test.dart';
import 'package:comwell_key_app/overview/cubit/overview_state.dart';
import 'package:comwell_key_app/share/share_booking_repository.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:comwell_key_app/overview/cubit/overview_cubit.dart';
import 'package:comwell_key_app/overview/models/booking.dart';
import 'package:comwell_key_app/overview/models/bookings.dart';
import 'package:comwell_key_app/overview/repository/overview_repository.dart';

class MockOverviewRepository extends Mock implements OverviewRepository {}
class MockShareBookingRepository extends Mock implements ShareBookingRepository {}

void main() {
  late OverviewCubit overviewCubit;
  late MockOverviewRepository mockOverviewRepository;
  late ShareBookingRepository shareBookingRepository;

  setUp(() {
    mockOverviewRepository = MockOverviewRepository();
    shareBookingRepository = MockShareBookingRepository();
    overviewCubit = OverviewCubit(mockOverviewRepository, shareBookingRepository);
  });

  tearDown(() {
    overviewCubit.close();
  });

  final mockBooking = Booking(
    id: '1',
    reservationStatus: ReservationStatus.newreservation,
    confirmationNumber: "s",
    roomNumber: '',
    startDate: DateTime(2021, 10, 10),
    endDate: DateTime(2021, 10, 10),
    image: '',
    hotelName: '',
    roomType: '',
    children: 2,
    adults: 2,
    hotelCode: '',
    firstName: "John",
    lastName: "Doe",
    bookerFirstName: "John",
    bookerLastName: "Doe",
    isPrimaryGuest: true,
    bookingDate: DateTime(2021, 10, 10),
    digitalCard: true,
    balance: 100,
    maskedCardNumber: "1234567890",
    addOnItems: const [],
  );

  group('OverviewCubit', () {
    blocTest<OverviewCubit, OverviewState>(
      'emits [OverviewLoading, OverviewLoaded] when fetchBookings is successful',
      build: () {
        when(() => mockOverviewRepository.fetchAllBookingsForUser()).thenAnswer(
          (_) async => Bookings(
            current: [mockBooking],
            past: const [],
            cancelled: const [],
          ),
        );
        return overviewCubit;
      },
      act: (cubit) => cubit.fetchBookings(),
      expect: () => [
        const OverviewState(isLoading: true),
        OverviewState(
          isLoading: true,
          bookings: Bookings(
            current: [mockBooking],
            past: const [],
            cancelled: const [],
          ),
        ),
        OverviewState(
          isLoading: false,
          bookings: Bookings(
            current: [mockBooking],
            past: const [],
            cancelled: const [],
          ),
        ),
      ],
    );

    blocTest<OverviewCubit, OverviewState>(
      'emits [OverviewLoading, OverviewError] when fetchBookings fails',
      build: () {
        when(
          () => mockOverviewRepository.fetchAllBookingsForUser(),
        ).thenThrow(Exception('Failed to fetch bookings'));
        return overviewCubit;
      },
      act: (cubit) => cubit.fetchBookings(),
      expect: () => [
        const OverviewState(isLoading: true),
        const OverviewState(isLoading: true, errorType: OverviewStateError.error),
        const OverviewState(isLoading: false, errorType: OverviewStateError.error),
      ],
    );

    blocTest<OverviewCubit, OverviewState>(
      'emits [OverviewLoaded] with updated bookings when addBooking is called',
      build: () {
        return overviewCubit;
      },
      seed: () => const OverviewState(
        bookings: Bookings(
          current: [],
          past: [],
          cancelled: [],
        ),
      ),
      act: (cubit) => cubit.addBooking(mockBooking),
      expect: () => [
        OverviewState(
          bookings: Bookings(
            current: [mockBooking],
            past: const [],
            cancelled: const [],
          ),
        ),
      ],
    );
  });
}