import 'package:flutter_test/flutter_test.dart';
import 'package:garden_planner/entities/beet.dart';
import 'package:garden_planner/entities/beet_row.dart';
import 'package:garden_planner/entities/plant.dart';
import 'package:garden_planner/entities/plant_in_row.dart';
import 'package:garden_planner/logic/beet.service.dart';
import 'package:garden_planner/logic/beet_row.service.dart';
import 'package:garden_planner/logic/plant.service.dart';

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

void main() {
  test('BeetRowService gethorizontalSpace should work', () {
    //Plant1 Horizontal 3
    //Plant2 Horizontal 6

    // Arrange
    final BeetRow row = BeetRow(0);
    final BeetRowService beetRowService = BeetRowService();
    final Plant plant = PlantGenerator.getPlant();
    final Plant plant2 = PlantGenerator.getPlant2();

    beetRowService.addPlant(row, plant);
    beetRowService.addPlant(row, plant2);

    // Act
    var getMaxHorizontalSpace = beetRowService.getTotalHorizontalSpace(row);

    // Assert
    // space = 0.6+0.25
    expect(getMaxHorizontalSpace, equals(0.85), reason: ' Space should be 0.8');
  });

  test('BeetRowService getHorizontalSpaceValue should work', () {
    //Plant1 Horizontal 3
    //Plant2 Horizontal 6

    // Arrange
    final BeetRow row = BeetRow(0);
    final BeetRowService beetRowService = BeetRowService();
    final Plant plant = PlantGenerator.getPlant();
    final Plant plant2 = PlantGenerator.getPlant2();

    beetRowService.addPlant(row, plant);
    beetRowService.addPlant(row, plant2);

    // Act
    var getMaxHorizontalSpaceValues =
        beetRowService.getHorizontalPlantingPosition(row);

    // Assert
    //  Every Row takes the half horizontal Space, because the Plant will be placed in the middle
    // for the second row, its the hole space of the previews and the half of the actual row
    var plantHorizontal1 = (0.6 / 2);
    var plantHorizontal2 = 0.6 + (0.25 / 2);

    expect(getMaxHorizontalSpaceValues,
        equals([plantHorizontal1, plantHorizontal2]),
        reason: 'value is not right ');
  });

  test('BeetRowService isActionNeeded should work', () {
    // Arrange
    final BeetRow row = BeetRow(0);

    final BeetRowService beetRowService = BeetRowService();
    final Plant plant = PlantGenerator.getPlant();
    final Plant plant2 = PlantGenerator.getPlant2();
    final PlantService plantService = PlantService();

    beetRowService.addPlant(row, plant);
    beetRowService.addPlant(row, plant2);

    // Act
    var actionShouldBeTrue = beetRowService.isActionNeeded(
        plantService, row, DateTime(2023, 05, 01));

    var actionShouldBeFalseBecauseNoEntry = beetRowService.isActionNeeded(
        plantService, row, DateTime(2023, 07, 01));
    var actionShouldBeFalse = beetRowService.isActionNeeded(
        plantService, row, DateTime(2023, 10, 01));

    // Assert
    expect(actionShouldBeTrue, equals(true), reason: 'action should be true ');
    expect(actionShouldBeFalse, equals(false),
        reason: 'action should be false because no entry ');
    expect(actionShouldBeFalseBecauseNoEntry, equals(false),
        reason: 'action should be false because its outside the date');
  });

  test('BeetRowService addPlant should work', () {
    // Arrange
    final BeetRow row = BeetRow(0);
    final BeetRowService beetRowService = BeetRowService();
    final Plant plant = PlantGenerator.getPlant();
    final Plant plant2 = PlantGenerator.getPlant2();

    // Act
    beetRowService.addPlant(row, plant);
    beetRowService.addPlant(row, plant2);

    // Assert
    expect(row.id, equals(0), reason: 'RowId is not 0');
    expect(row.plants.length, equals(2), reason: 'Not all plants add');

    expect(row.plants[0], isA<PlantInRow>(),
        reason: 'plant1 not the right type');
    expect(row.plants[1], isA<PlantInRow>(),
        reason: 'plant2 not the right type');

    expect(row.plants[0].id, equals(plant.id),
        reason: 'plant1 is not the right plant');
    expect(row.plants[1].id, equals(plant2.id),
        reason: 'plant2 is not the right plant');
  });

  test('BeetRowService removePlantFromRowById should work', () {
    // Arrange
    final BeetRow row = BeetRow(0);
    final BeetRowService beetRowService = BeetRowService();
    final Plant plant = PlantGenerator.getPlant();
    final Plant plant2 = PlantGenerator.getPlant2();

    beetRowService.addPlant(row, plant);
    beetRowService.addPlant(row, plant2);
    beetRowService.addPlant(row, plant);

    // Act

    beetRowService.removePlantFromRowById(row, 1);

    // Assert
    expect(row.plants.length, equals(2), reason: 'Row was not deleted');
    expect(row.plants[0].id, equals(plant.id),
        reason: 'Row 1 is not the right');
    expect(row.plants[1].id, equals(plant.id),
        reason: 'Row 1 is not the right');
  });

  test('BeetRowService removePlantFromRowById should throw no Exception', () {
    // Arrange
    final BeetRow row = BeetRow(0);
    final BeetRowService beetRowService = BeetRowService();
    final Plant plant = PlantGenerator.getPlant();

    beetRowService.addPlant(row, plant);

    // Act

    beetRowService.removePlantFromRowById(row, 14);

    // Assert
    // No exception should be thrown
  });

  test('BeetRowService removePlantFromRowById should work', () {
    // Arrange
    final BeetService beetService = BeetService();
    final Beet beet = Beet();
    final BeetRowService beetRowService = BeetRowService();
    final Plant plant1 = PlantGenerator.getPlant();
    final Plant plant2 = PlantGenerator.getPlant2();

    beetService.addNewRow(beet);
    beetService.addNewRow(beet);

    beetService.addPlantToRowById(beet, beetRowService, 0, plant1);

    beetService.addPlantToRowById(beet, beetRowService, 1, plant1);

    beetService.addPlantToRowById(beet, beetRowService, 1, plant2);
    // Act

    var row = beetRowService.getRowById(beet, 1);

    // Assert
    expect(row.plants.length, equals(2), reason: 'Is the wrong row returned');
    expect(row.plants[1].id, equals(plant2.id),
        reason: 'Is the wrong row returned');
  });

  // DB Tests will be in next Release
}
