import 'dart:convert';

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

class LoginCredentials {
  final String username;
  final String password;
  const LoginCredentials(this.username, this.password);

  Map<String, dynamic> toJson() {
    return {
      'username': username,
      'password': password,
    };
  }
}

class TokenResponse {
  final String token;
  const TokenResponse(this.token);

  factory TokenResponse.fromJson(Map<String, dynamic> json) {
    return switch (json) {
      {'token': String token} => TokenResponse(token),
      _ => throw const FormatException('Invalid token response format.'),
    };
  }
}

Future<String> postLogin(LoginCredentials credentials) async {
  final http.Response response = await http.post(
      Uri.parse('http://localhost:8080/api/login'),
      body: jsonEncode(credentials.toJson()),
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      }
  );
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body) as Map<String, dynamic>;
    final TokenResponse obj = TokenResponse.fromJson(data);
    return obj.token;
  } else {
    throw Exception('Failed to log in.');
  }
}

Future<bool> getUsernameAvailability(String username) async {
  final http.Response response = await http.get(
    Uri.parse('http://localhost:8080/api/register/username-availability?username=$username'),
  );
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return data['available'] as bool;
  } else {
    return false;
  }
}

Future<String> postRegister(LoginCredentials credentials) async {
  final bodyContent = jsonEncode(credentials.toJson());
  final http.Response response = await http.post(
    Uri.parse('http://localhost:8080/api/register'),
    body: bodyContent,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'Content-Length': bodyContent.length.toString()
    }
  );
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body) as Map<String, dynamic>;
    return TokenResponse.fromJson(data).token;
  } else {
    print(response);
    throw Exception('Registration failed.');
  }
}

Future<void> deleteUser(String token) async {
  final http.Response response = await http.delete(
    Uri.parse('http://localhost:8080/api/me'),
    headers: {
      'Authorization': 'Bearer $token'
    }
  );
  if (response.statusCode != 200) {
    throw Exception('Deleting user failed.');
  }
}
