import "package:flutter/services.dart";
import "package:flutter_test/flutter_test.dart";
import "package:inventree/api.dart";
import "package:inventree/user_profile.dart";

// This is the same as the following issue except it keeps the http client
// TestWidgetsFlutterBinding.ensureInitialized();
class CustomBinding extends AutomatedTestWidgetsFlutterBinding {
  @override
  bool get overrideHttpClient => false;
}

void setupTestEnv() {
  // Uses custom binding to not override the http client
  CustomBinding();

  // Mock the path provider
  const MethodChannel channel = MethodChannel("plugins.flutter.io/path_provider");
  TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
      .setMockMethodCallHandler(channel, (MethodCall methodCall) async {
    return ".";
  });
}

// Accessors for default testing values
const String testServerAddress = "http://localhost:8000/";
const String testServerName = "Test Server";
const String testUsername = "testuser";
const String testPassword = "testpassword";


/*
 * Request an API token for the given profile
 */
Future<bool> fetchProfileToken({
  UserProfile? profile,
  String username = testUsername,
  String password = testPassword
}) async {

  profile ??= await UserProfileDBManager().getProfileByName(testServerName);

  assert(profile != null);

  final response = await InvenTreeAPI().fetchToken(profile!, username, password);
  return response.successful();
}


/*
 * Setup a valid profile, and return it
 */
Future<UserProfile> setupServerProfile({bool select = true, bool fetchToken = false}) async {
  // Setup a valid server profile

  UserProfile? profile = await UserProfileDBManager().getProfileByName(testServerName);

  if (profile == null) {
    // Profile does not already exist - create it!
    bool result = await UserProfileDBManager().addProfile(
        UserProfile(
          server: testServerAddress,
          name: testServerName
        )
    );

    assert(result);
  }

  profile = await UserProfileDBManager().getProfileByName(testServerName);
  assert(profile != null);

  if (select) {
    assert(await UserProfileDBManager().selectProfileByName(testServerName));
  }

  if (fetchToken && !profile!.hasToken) {
    final bool result = await fetchProfileToken(profile: profile);
    assert(result);
    assert(profile.hasToken);
  }

  return profile!;
}


/*
 * Complete all steps necessary to login to the server
 */
Future<void> connectToTestServer() async {

  // Setup profile, and fetch user token as necessary
  final profile = await setupServerProfile(fetchToken: true);

  // Connect to the server
  assert(await InvenTreeAPI().connectToServer(profile));
}