import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:travel_mate/models/trip.dart';

void main() {
  group('Trip Model Tests', () {
    const id = 'trip1';
    const title = 'Summer Vacation';
    const description = 'Trip to the beach';
    const location = 'Miami';
    final startDate = DateTime(2023, 6, 1);
    final endDate = DateTime(2023, 6, 10);
    const createdBy = 'user1';
    final createdAt = DateTime(2023, 1, 1);
    final updatedAt = DateTime(2023, 1, 2);
    const budget = 2000.0;
    const participants = ['user1', 'user2', 'user3'];

    final trip = Trip(
      id: id,
      title: title,
      description: description,
      location: location,
      startDate: startDate,
      endDate: endDate,
      createdBy: createdBy,
      createdAt: createdAt,
      updatedAt: updatedAt,
      budget: budget,
      participants: participants,
      status: 'active',
    );

    test('supports value equality', () {
      final trip2 = Trip(
        id: id,
        title: title,
        description: description,
        location: location,
        startDate: startDate,
        endDate: endDate,
        createdBy: createdBy,
        createdAt: createdAt,
        updatedAt: updatedAt,
        budget: budget,
        participants: participants,
        status: 'active',
      );
      expect(trip, equals(trip2));
    });

    group('Helpers', () {
      test('durationInDays returns correct number of days', () {
        // 1st to 10th inclusive = 10 days
        expect(trip.durationInDays, 10);
      });

      test('totalParticipants includes creator + participants list count?', () {
        // Source code says: participants.length + 1
        // participants has 3 items. So total should be 4.
        expect(trip.totalParticipants, 4);
      });

      test('budgetPerParticipant calculation', () {
        // 2000 / 4 = 500
        expect(trip.budgetPerParticipant, 500.0);
      });

      test(
        'status checks logic (mocking DateTime.now is tricky without injection, skipping exact time logic or testing logic assumption only)',
        () {
          // For simple unit tests without time mocking, we can create trips with dates relative to "now".
          final now = DateTime.now();

          final pastTrip = trip.copyWith(
            startDate: now.subtract(const Duration(days: 10)),
            endDate: now.subtract(const Duration(days: 5)),
            status: 'completed',
          );
          expect(pastTrip.isCompleted, isTrue);

          final futureTrip = trip.copyWith(
            startDate: now.add(const Duration(days: 5)),
            endDate: now.add(const Duration(days: 10)),
            status: 'active',
          );
          expect(futureTrip.isUpcoming, isTrue);

          final activeTrip = trip.copyWith(
            startDate: now.subtract(const Duration(days: 2)),
            endDate: now.add(const Duration(days: 2)),
            status: 'active',
          );
          expect(activeTrip.isActive, isTrue);
        },
      );
    });

    group('fromMap', () {
      test('parses standard Map inputs correctly', () {
        final map = {
          'title': title,
          'description': description,
          'location': location,
          'startDate': startDate
              .toIso8601String(), // _parseDateTime handles String
          'endDate': Timestamp.fromDate(
            endDate,
          ), // _parseDateTime handles Timestamp
          'createdBy': createdBy,
          'createdAt':
              createdAt.millisecondsSinceEpoch, // _parseDateTime handles int
          'updatedAt': updatedAt, // _parseDateTime handles DateTime
          'budget': budget,
          'participants': participants,
          'status': 'active',
        };
        final fromMapTrip = Trip.fromMap(map, id);

        expect(fromMapTrip.id, id);
        expect(fromMapTrip.title, title);
        // Dates might vary slightly due to precision if using milliseconds vs microseconds, checking explicitly later
        expect(fromMapTrip.description, description);
        expect(fromMapTrip.budget, budget);
      });
    });
  });
}
