import 'package:flutter_test/flutter_test.dart';
import 'package:tane/data/export_import/inventory_csv_codec.dart';
import 'package:tane/data/species_repository.dart';
import 'package:tane/db/database.dart';
import 'package:tane/db/enums.dart';

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

void main() {
  const codec = InventoryCsvCodec();
  const tomato = SpeciesSeed(
    scientificName: 'Solanum lycopersicum',
    family: 'Solanaceae',
  );

  late AppDatabase db;

  setUp(() => db = newTestDatabase());
  tearDown(() => db.close());

  test('inserts a variety with its lot, resolving species by name', () async {
    await newTestSpeciesRepository(db).seedBundled(const [tomato]);
    final repo = newTestRepository(db);

    const csv =
        'variety_label,category,species_scientific_name,'
        'cultivar_name,lot_type,harvest_year,quantity_kind,quantity_precise\r\n'
        'Grandma tomato,Solanaceae,Solanum lycopersicum,Marmande,seed,2024,cob,3\r\n';
    final summary = await repo.importCsv(codec.decode(csv));
    expect(summary.inserted, 1);

    final variety = await db.select(db.varieties).getSingle();
    expect(variety.label, 'Grandma tomato');
    expect(variety.cultivarName, 'Marmande');
    final species = await db.select(db.species).getSingle();
    expect(variety.speciesId, species.id);

    final lot = await db.select(db.lots).getSingle();
    expect(lot.varietyId, variety.id);
    expect(lot.type, LotType.seed);
    expect(lot.harvestYear, 2024);
    expect(lot.quantityKind, 'cob');
    expect(lot.quantityPrecise, 3.0);
  });

  test('an unmatched species name leaves speciesId null', () async {
    final repo = newTestRepository(db); // no bundled catalog
    const csv =
        'variety_label,species_scientific_name\r\n'
        'Mystery bean,Phaseolus nonexistus\r\n';
    await repo.importCsv(codec.decode(csv));
    final variety = await db.select(db.varieties).getSingle();
    expect(variety.speciesId, isNull);
  });

  test('is additive: importing the same CSV twice adds it twice', () async {
    final repo = newTestRepository(db);
    const csv = 'variety_label\r\nTomato\r\n';
    await repo.importCsv(codec.decode(csv));
    await repo.importCsv(codec.decode(csv));
    final varieties = await db.select(db.varieties).get();
    expect(varieties, hasLength(2));
  });

  test(
    'stores vernacular names and links attached to the new variety',
    () async {
      final repo = newTestRepository(db);
      const csv =
          'variety_label,vernacular_names,external_links\r\n'
          'Tomato,"tomate (es); granny tomato","Wiki|https://example.org"\r\n';
      await repo.importCsv(codec.decode(csv));

      final variety = await db.select(db.varieties).getSingle();
      final names = await db.select(db.varietyVernacularNames).get();
      expect(
        names.map((n) => n.name),
        containsAll(['tomate', 'granny tomato']),
      );
      expect(names.every((n) => n.varietyId == variety.id), isTrue);

      final links = await db.select(db.externalLinks).get();
      expect(links.single.url, 'https://example.org');
      expect(links.single.parentId, variety.id);
    },
  );
}
