import 'package:flutter_test/flutter_test.dart';
import 'package:garden_planner/api/garden_api.service.dart';
import 'package:garden_planner/entities/beet_entry_return.dart';

import '../helpers/plant_generator.dart';
import '../mock/mock_http_client.dart';

void main() {
  late GardenApiService gardenApiService;

  setUp(() {
    gardenApiService = GardenApiService(MockHttpClient());
  });

  test('Test getAllPlants', () async {
    // Arrange
    final expectedPlants = [
      PlantGenerator.getPlant(),
      PlantGenerator.getPlant2()
    ];

    // Act
    final result = (await gardenApiService.getAllAvailablePlants()).toList();

    // Assert
    for (int i = 0; i < result.length; i++) {
      expect(result[i].name, equals(expectedPlants[i].name),
          reason: "Name is not equal");
      expect(result[i].supType, equals(expectedPlants[i].supType),
          reason: "Description is not equal");
      expect(result[i].verticalSpace, equals(expectedPlants[i].verticalSpace),
          reason: "Vertical space is not equal");
      expect(
          result[i].horizontalSpace, equals(expectedPlants[i].horizontalSpace),
          reason: "Horizontal space is not equal");
      expect(result[i].times.length, equals(expectedPlants[i].times.length),
          reason: "Times length is not equal");
      expect(result[i].image, equals(expectedPlants[i].image),
          reason: "Image path is not equal");
      expect(result[i].waterRequirement,
          equals(expectedPlants[i].waterRequirement),
          reason: "Water requirement is not equal");

      for (int j = 0; j < result[i].times.length; j++) {
        expect(result[i].times[j].description,
            equals(expectedPlants[i].times[j].description),
            reason: "Time description is not equal Plant:$i Time:$j");
        expect(result[i].times[j].action,
            equals(expectedPlants[i].times[j].action),
            reason: "Time action is not equal Plant:$i Time:$j");
        expect(
            result[i].times[j].until, equals(expectedPlants[i].times[j].until),
            reason: "Time until is not equal Plant:$i Time:$j");
        expect(result[i].times[j].from, equals(expectedPlants[i].times[j].from),
            reason: "Time from is not equal Plant:$i Time:$j");
      }
    }
  });

  test('Test loadBeet', () async {
    // Arrange
    final expectedBeetEntries = [
      BeetApiEntryReturn(PlantGenerator.getPlant2(), 0),
      BeetApiEntryReturn(PlantGenerator.getPlant(), 0),
      BeetApiEntryReturn(PlantGenerator.getPlant2(), 1),
      BeetApiEntryReturn(PlantGenerator.getPlant(), 1)
    ];
    // Act
    var beetEntries = await gardenApiService.getBeet();

    // Assert
    expect(
      beetEntries.length,
      equals(expectedBeetEntries.length),
      reason: 'Number of beet entries is not equal',
    );

    for (int i = 0; i < beetEntries.length; i++) {
      expect(
        beetEntries[i].plant.id,
        equals(expectedBeetEntries[i].plant.id),
        reason: 'plant $i is not equal',
      );
      expect(
        beetEntries[i].plant.times.length,
        equals(expectedBeetEntries[i].plant.times.length),
        reason: 'plant.times.length at index $i is not equal',
      );
      expect(
        beetEntries[i].beetRow,
        equals(expectedBeetEntries[i].beetRow),
        reason: 'beetrow at index $i is not equal',
      );
    }
  });

  test('Test getPlant', () async {
    // Arrange
    final expectedPlant = PlantGenerator.getPlant();

    // Act
    final plant = await gardenApiService.getPlant(1);

    // Assert
    expect(plant.id, equals(expectedPlant.id), reason: 'Plant ID is not equal');
    expect(plant.name, equals(expectedPlant.name),
        reason: 'Plant Name is not equal');
    expect(plant.supType, equals(expectedPlant.supType),
        reason: 'Plant SubType is not equal');
    expect(plant.waterRequirement, equals(expectedPlant.waterRequirement),
        reason: 'Plant Waterrewuirement is not equal');
    expect(plant.horizontalSpace, equals(expectedPlant.horizontalSpace),
        reason: 'Plant horizontalSpace is not equal');
    expect(plant.verticalSpace, equals(expectedPlant.verticalSpace),
        reason: 'Plant verticalSpace is not equal');
    expect(plant.image, equals(expectedPlant.image),
        reason: 'Plant image length is not equal');

    expect(plant.times.length, equals(expectedPlant.times.length),
        reason: 'Planttimes length is not equal');
    for (int j = 0; j < plant.times.length; j++) {
      final time = plant.times[j];
      final expectedTime = expectedPlant.times[j];

      expect(time.description, equals(expectedTime.description),
          reason: 'Planttimes description is not equal');
      expect(time.from, equals(expectedTime.from),
          reason: 'Planttimes from is not equal');
      expect(time.until, equals(expectedTime.until),
          reason: 'Planttimes until is not equal');
      expect(time.action, equals(expectedTime.action),
          reason: 'Planttimes action description is not equal');
    }
  });
}
