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

import '../../model/endpointData.dart';
import '../apiParams.dart';
import '../apiRequest.dart';
import '../apiResponse.dart';
import 'queries/authenticate/authenticate.dart';
import 'webuntisError.dart';

abstract class WebuntisApi extends ApiRequest {
  Uri endpoint = Uri.parse("https://${EndpointData().webuntis().full()}/WebUntis/jsonrpc.do?school=marianum-fulda");
  String method;
  ApiParams? genericParam;
  http.Response? response;

  bool authenticatedResponse;

  WebuntisApi(this.method, this.genericParam, {this.authenticatedResponse = true});


  Future<String> query(WebuntisApi untis) async {
    String query = '{"id":"ID","method":"$method","params":${untis._body()},"jsonrpc":"2.0"}';

    String sessionId = "0";
    if(authenticatedResponse) {
      sessionId = (await Authenticate.getSession()).sessionId;
    }
    http.Response data = await post(query, {"Cookie": "JSESSIONID=$sessionId"});
    response = data;

    dynamic jsonData = jsonDecode(data.body);
    if(jsonData['error'] != null) {
      if(jsonData['error']['code'] == -8520) {
        await Authenticate.createSession();
        this.query(untis);
      } else {
        throw WebuntisError(jsonData['error']['message'], jsonData['error']['code']);
      }
    }
    return data.body;
  }

  dynamic finalize(dynamic response) {
    response.rawResponse = this.response!;
    return response;
  }

  Future<ApiResponse> run();

  String _body() {
    return genericParam == null ? "{}" : jsonEncode(genericParam);
  }

  Future<http.Response> post(String data, Map<String, String>? headers) async {
    return await http
        .post(endpoint, body: data, headers: headers)
        .timeout(
        const Duration(seconds: 10),
        onTimeout: () => throw WebuntisError("Timeout", 1)
    );
  }
}