import 'dart:convert';

import 'package:oauth2/oauth2.dart' as oauth2;

Future<String> getSessionCookie(oauth2.Client client) async {
  final response0 = await client.get(
    Uri.parse(
      'https://auth.leinelab.org/api/v3/flows/instances/default-user-settings-flow/execute/',
    ),
  );

  var sessionCookieHeader = response0.headers['set-cookie'];
  if (sessionCookieHeader == null) {
    throw Exception('No session cookie found in response headers.');
  }

  String? sessionCookie;
  int index = sessionCookieHeader.indexOf(';');
  sessionCookie = (index == -1)
      ? sessionCookieHeader
      : sessionCookieHeader.substring(0, index);

  print("Session cookie: $sessionCookie");

  return sessionCookie;
}

Future<Map<String, dynamic>> getUserSettings(
  oauth2.Client client,
  String sessionCookie,
) async {
  final response = await client.get(
    Uri.parse(
      'https://auth.leinelab.org/api/v3/flows/executor/default-user-settings-flow/?query=',
    ),
    headers: {'Cookie': sessionCookie},
  );

  final flowJson = jsonDecode(response.body);

  if (flowJson['fields'] == null) {
    throw Exception("Expected 'fields' in response, but got: ${response.body}");
  }

  final fields = flowJson['fields'] as List<dynamic>;
  Map<String, dynamic> userSettingsObj = {};
  for (var field in fields) {
    if (field['field_key'] == null || field['initial_value'] == null) {
      throw Exception(
        "Expected 'field_key' and 'initial_value' in field, but got: $field",
      );
    }

    userSettingsObj[field['field_key']] = field['initial_value'];
  }

  return userSettingsObj;
}

Future<void> setUserSettings(
  oauth2.Client client,
  String sessionCookie,
  Object data,
) async {
  final body = jsonEncode(data);

  final response = await client.post(
    Uri.parse(
      'https://auth.leinelab.org/api/v3/flows/executor/default-user-settings-flow/?query=',
    ),
    body: body,
    headers: {'Content-Type': 'application/json', 'Cookie': sessionCookie},
  );

  // Authentik expects a redirect after the POST request and only writes
  // the data to the database after fetching the redirect location.
  if (response.statusCode != 302) {
    throw Exception(
      "Expected a redirect (302) response, but got ${response.statusCode}",
    );
  }

  final newLocation = response.headers['location'];
  if (newLocation == null) {
    throw Exception("No redirect location found in response headers.");
  }

  final responseFinal = await client.get(
    Uri.parse('https://auth.leinelab.org/' + newLocation),
    headers: {'Cookie': sessionCookie},
  );

  if (responseFinal.statusCode == 200) {
    print("User data updated successfully.");
    print("responseFinal body:");
    print(responseFinal.body);
    responseFinal.headers.toString().split('\n').forEach(print);
  } else {
    print("Error updating user data: ${responseFinal.statusCode}");
    print("responseFinal body:");
    print(responseFinal.body);
    print(responseFinal.headers.toString());
  }
}
