import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:logger/logger.dart';
import 'package:prasule/api/category.dart';
import 'package:prasule/api/entry_data.dart';
import 'package:prasule/api/wallet.dart';
import 'package:prasule/api/wallet_entry.dart';
import 'package:prasule/api/wallet_manager.dart';

import 'package:prasule/main.dart';
import 'package:prasule/pw/platformfield.dart';

void main() {
  final logger = Logger();
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group("Test classes and API", () {
    test("Test wallet operations", () async {
      expect(
        (await WalletManager.listWallets()).length,
        equals(0),
      ); // check that there are no other wallets
      await WalletManager.saveWallet(Wallet.empty);
      var w = (await WalletManager.listWallets()).firstOrNull;
      expect(w, isNotNull); // check that the wallet was successfully saved
      expect(w!.categories.length, equals(1));
      w.categories.add(
        WalletCategory(
          name: "Testing",
          id: w.nextCategoryId,
          icon: Icons.abc,
          color: Colors.orange,
        ),
      ); // create test category
      final testId = w.nextId;
      w.entries.add(
        WalletSingleEntry(
          data: EntryData(amount: 200, name: "Automated"),
          type: EntryType.expense,
          date: DateTime.now(),
          category: w.categories.last,
          id: w.nextId,
        ),
      ); // create test entry
      await WalletManager.saveWallet(w); // save again
      w = await WalletManager.loadWallet(w.name); // try loading manually
      final e = w.entries.where((element) => element.id == testId).firstOrNull;
      expect(
        e,
        isNotNull,
      ); // check that the entry was successfully created
      expect(
        w.categories.where((element) => element.id == e!.category.id).length,
        equals(1),
      ); // check that the category exists too

      await WalletManager.deleteWallet(w);
      expect(
        (await WalletManager.listWallets()).length,
        equals(0),
      );
    });
  });

  group("Test app functionality:", () {
    testWidgets('First-time setup', (WidgetTester tester) async {
      // Delete all data
      await WalletManager.deleteAllData();
      // Build our app and trigger a frame.
      await tester.pumpWidget(
        const MyApp(
          locale: Locale('en', 'US'),
        ),
      );
      await tester.pumpAndSettle();
      logger.i("Looking for welcome header");
      expect(find.text('Welcome!'), findsOneWidget);

      // Tap "Next" button
      await tester.tap(find.text("Next"));
      await tester.pumpAndSettle();

      logger.i("Next view, looking for name+balance fields");

      final firstFields = find.byType(PlatformField);

      expect(firstFields, findsExactly(2));

      logger.i("Entering text");
      await tester.enterText(find.byType(PlatformField).first, "Debugging");
      await tester.pumpAndSettle();
      await tester.enterText(find.byType(PlatformField).last, "100");
      await tester.pumpAndSettle();

      // Tap "Next" button
      await tester.tap(find.text("Next"));
      await tester.pumpAndSettle();

      // Tap "Finish" button
      await tester.tap(find.text("Finish"));
      await tester.pumpAndSettle();

      expect(
        find.byWidgetPredicate(
          (widget) =>
              widget is DropdownButton &&
              ((widget as DropdownButton<int>).value ?? -1) == 0,
        ),
        findsOne,
      );
    });

    testWidgets('Test rendering of entries', (WidgetTester tester) async {
      // Delete all data
      await WalletManager.deleteAllData();
      expect((await WalletManager.listWallets()).length, equals(0));

      // Create test data
      final w = Wallet.empty;
      await w.createTestEntries();
      expect((await WalletManager.listWallets()).length, equals(1));

      // Build our app and trigger a frame.
      await tester.pumpWidget(
        const MyApp(
          locale: Locale('en', 'US'),
        ),
      );
      await tester.pumpAndSettle();

      // TODO: better test

      expect(
        find.byType(ListTile, skipOffstage: false),
        findsAtLeast(10),
      );
    });
  });
}
