import 'package:commons_core/commons_core.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tane/data/species_repository.dart';
import 'package:tane/data/variety_repository.dart';
import 'package:tane/db/database.dart';
import 'package:tane/db/enums.dart';

import '../support/test_support.dart';

void main() {
  late AppDatabase db;
  late VarietyRepository repo;

  setUp(() {
    db = newTestDatabase();
    repo = newTestRepository(db);
  });
  tearDown(() => db.close());

  test('addLot and updateLot persist the share terms', () async {
    final id = await repo.addQuickVariety(label: 'Maize');
    final lotId = await repo.addLot(
      varietyId: id,
      offerStatus: OfferStatus.shared,
    );

    var detail = await repo.watchVariety(id).first;
    expect(detail!.lots.single.offerStatus, OfferStatus.shared);

    await repo.updateLot(
      lotId: lotId,
      type: LotType.seed,
      offerStatus: OfferStatus.exchange,
    );
    detail = await repo.watchVariety(id).first;
    expect(detail!.lots.single.offerStatus, OfferStatus.exchange);
  });

  test('list items flag varieties with some lot offered', () async {
    final sharedId = await repo.addQuickVariety(label: 'Shared bean');
    await repo.addLot(varietyId: sharedId, offerStatus: OfferStatus.sell);
    final privateId = await repo.addQuickVariety(label: 'Private bean');
    await repo.addLot(varietyId: privateId);

    final items = await repo.watchInventoryView().first;
    final byLabel = {for (final i in items.items) i.label: i};
    expect(byLabel['Shared bean']!.isShared, isTrue);
    expect(byLabel['Private bean']!.isShared, isFalse);
  });

  test('sharedCatalog lists only offered lots, sorted and joined', () async {
    final species = newTestSpeciesRepository(db);
    await species.seedBundled(const [
      SpeciesSeed(
        scientificName: 'Zea mays',
        family: 'Poaceae',
        commonNames: {
          'en': ['Maize'],
        },
      ),
    ]);

    final maizeId = await repo.addQuickVariety(label: 'Rebordanes maize');
    final matches = await species.search('Zea', languageCode: 'en');
    await repo.linkSpecies(maizeId, matches.single.id);
    await repo.addLot(
      varietyId: maizeId,
      harvestYear: 2024,
      quantity: const Quantity(kind: QuantityKind.cob, count: 2),
      offerStatus: OfferStatus.shared,
    );
    // A private lot of the same variety stays out of the catalog.
    await repo.addLot(varietyId: maizeId, harvestYear: 2023);

    final beanId = await repo.addQuickVariety(label: 'Alubia de Tolosa');
    await repo.addLot(
      varietyId: beanId,
      abundance: Abundance.plentyToShare,
      offerStatus: OfferStatus.exchange,
    );

    // A deleted shared lot disappears with its tombstone.
    final goneId = await repo.addQuickVariety(label: 'Gone');
    final goneLot = await repo.addLot(
      varietyId: goneId,
      offerStatus: OfferStatus.shared,
    );
    await repo.softDeleteLot(goneLot);

    final catalog = await repo.sharedCatalog();
    expect(catalog, hasLength(2));
    // Sorted by label, case-insensitively.
    expect(catalog.first.varietyLabel, 'Alubia de Tolosa');
    expect(catalog.first.offerStatus, OfferStatus.exchange);
    expect(catalog.first.abundance, Abundance.plentyToShare);

    final maize = catalog.last;
    expect(maize.varietyLabel, 'Rebordanes maize');
    expect(maize.scientificName, 'Zea mays');
    expect(maize.category, 'Poaceae');
    expect(maize.harvestYear, 2024);
    expect(maize.quantity!.count, 2);
  });
}
