import 'dart:developer';

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

import '../../../model/accountData.dart';
import '../../../model/endpointData.dart';
import '../../apiError.dart';
import '../../apiParams.dart';
import '../../apiRequest.dart';
import '../../apiResponse.dart';

enum TalkApiMethod {
  get,
  post,
  put,
  delete,
}

abstract class TalkApi<T extends ApiResponse?> extends ApiRequest {
  String path;
  ApiParams? body;
  Map<String, String>? headers = {};
  Map<String, dynamic>? getParameters;

  http.Response? response;

  TalkApi(this.path, this.body, {this.headers, this.getParameters});

  Future<http.Response>? request(Uri uri, ApiParams? body, Map<String, String>? headers);
  T assemble(String raw);

  Future<T> run() async {
    getParameters?.forEach((key, value) {
      getParameters?.update(key, (value) => value.toString());
    });

    Uri endpoint = Uri.https('${AccountData().buildHttpAuthString()}@${EndpointData().nextcloud().domain}', '${EndpointData().nextcloud().path}/ocs/v2.php/apps/spreed/api/$path', getParameters);

    headers ??= {};
    headers?.putIfAbsent('Accept', () => 'application/json');
    headers?.putIfAbsent('OCS-APIRequest', () => 'true');

    http.Response? data;

    try {
      data = await request(endpoint, body, headers);
      if(data == null) throw Exception('No response Data');
      if(data.statusCode >= 400 || data.statusCode < 200) throw Exception("Response status code '${data.statusCode}' might indicate an error");
    } catch(e) {
      log(e.toString());
      throw ApiError('Request $endpoint could not be dispatched: ${e.toString()}');
    }
    //dynamic jsonData = jsonDecode(data.body);

    T assembled;
    try {
      assembled = assemble(data.body);
      assembled?.headers = data.headers;
      return assembled;
    } catch (e) {
      // TODO report error
      log('Error assembling Talk API ${T.toString()} message: ${e.toString()} response on ${endpoint.path} with request body: $body and request headers: ${headers.toString()}');
    }

    throw Exception('Error assembling Talk API response');
  }

}