import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:excelso_attendance/main.dart';
import 'package:excelso_attendance/resource/strings.dart';
import 'package:http/http.dart' as http;

int typeGet = 1;
int typePost = 2;

class ConstantApi {
  static int timeOutInSecond = 20;

  static Future<HttpResponseApi> httpRequest(
      int typeRequest, String apiUrl, String namaFungsi,
      {String? bodies = ''}) async {
    http.Response apiResult;
    try {

      if (typeRequest == typePost) {
        apiResult = await http
            .post(Uri.parse(apiUrl),
                headers: {"Content-Type": "application/json"}, body: bodies)
            .timeout(Duration(seconds: timeOutInSecond));
      } else if (typeRequest == typeGet) {
        apiResult = await http.get(
          Uri.parse(apiUrl),
          headers: {"Content-Type": "application/json"},
        ).timeout(Duration(seconds: timeOutInSecond));
      } else {
        if (debug) {
          // ignore: avoid_print
          print('HTTP REQUEST => TIPE REQUEST TIDAK VALID');
        }
        return HttpResponseApi(
          succes: false,
          msg: Strings.wrongMethod,
          apiResponse: ApiResponse(
            error: true,
            msg: Strings.wrongMethod,
          ),
        );
      }
      if (apiResult.statusCode.toString().startsWith("2")) {
        try {
          final jsonObject = jsonDecode(apiResult.body);
          // kalau codenya 2xx, jangan isi api response, biar nanti di kelola di viewmodel response dari server
          return HttpResponseApi(
            succes: true,
            code: apiResult.statusCode,
            msg: Strings.success,
            jsonObject: jsonObject,
          );
        } catch (e) {
          return HttpResponseApi(
            succes: false,
            msg:
                "${Strings.serverError}, statusCode: ${apiResult.statusCode}, msg: body can`t decode ",
            apiResponse: ApiResponse(
              error: true,
              msg:
                  "${Strings.serverError}, statusCode: ${apiResult.statusCode}, msg: body can`t decode ",
            ),
          );
        }
      } else if (apiResult.statusCode.toString().startsWith("4")) {
        try {
          final jsonObject = jsonDecode(apiResult.body);
          return HttpResponseApi(
            succes: false,
            code: apiResult.statusCode,
            msg: Strings.success,
            jsonObject: jsonObject,
            apiResponse: ApiResponse(
                error: true,
                msg: jsonObject['msg'] ?? Strings.noMessageFromServer,
                data: jsonObject['code'] ?? "UNKNOWN CODE"),
          );
        } catch (e) {
          return HttpResponseApi(
            succes: false,
            msg:
                "${Strings.serverError}, statusCode: ${apiResult.statusCode}, msg: body can`t decode ",
            apiResponse: ApiResponse(
              error: true,
              msg:
                  "${Strings.serverError}, statusCode: ${apiResult.statusCode}, msg: body can`t decode ",
            ),
          );
        }
      } else if (apiResult.statusCode.toString().startsWith("5")) {
        // return HttpResponseApi(
        //   succes: false,
        //   code: apiResult.statusCode,
        //   msg: "${Strings.serverError}, statusCode: ${apiResult.statusCode}",
        // );
        try {
          final jsonObject = jsonDecode(apiResult.body);
          return HttpResponseApi(
            succes: false,
            code: apiResult.statusCode,
            msg: Strings.success,
            jsonObject: jsonObject,
            apiResponse: ApiResponse(
              error: true,
              msg: jsonObject['msg'] ?? Strings.noMessageFromServer,
              data: jsonObject['code'] ?? "UNKNOWN CODE",
            ),
          );
        } catch (e) {
          return HttpResponseApi(
            succes: false,
            code: apiResult.statusCode,
            msg: "${Strings.serverError}, statusCode: ${apiResult.statusCode}",
            apiResponse: ApiResponse(
              error: true,
              msg:
                  "${Strings.serverError}, statusCode: ${apiResult.statusCode}",
            ),
          );
        }
      } else {
        return HttpResponseApi(
          succes: false,
          code: apiResult.statusCode,
          msg:
              "${Strings.serverError}, statusCode: ${apiResult.statusCode}, msg: ${Strings.uknownError}",
          apiResponse: ApiResponse(
            error: true,
            msg:
                "${Strings.serverError}, statusCode: ${apiResult.statusCode}, msg: ${Strings.uknownError}",
          ),
        );
      }
    } on TimeoutException catch (_) {
      return HttpResponseApi(
        succes: false,
        msg: Strings.timeoutException,
        apiResponse: ApiResponse(
          error: true,
          msg: Strings.timeoutException,
        ),
      );
    } on SocketException catch (e) {
      return HttpResponseApi(
        succes: false,
        msg: "${Strings.cantConnectToServer}, $e",
        apiResponse: ApiResponse(
          error: true,
          msg: "${Strings.cantConnectToServer}, $e",
        ),
      );
    } on HttpException catch(e) {
      return HttpResponseApi(
        succes: false,
        msg: "${Strings.clientError}, Terjadi kendala pada koneksi http, silakan cek kembali koneksi internet anda. Err: ${e.message}",
        apiResponse: ApiResponse(
          error: true,
          msg: "${Strings.clientError}, Terjadi kendala pada koneksi http, silakan cek kembali koneksi internet anda. Err: ${e.message}",
        ),
      );
    } on http.ClientException catch (e) {
      return HttpResponseApi(
        succes: false,
        msg: "${Strings.clientError}, Terjadi kendala pada koneksi, silakan cek kembali koneksi internet anda. Err: ${e.message}",
        apiResponse: ApiResponse(
          error: true,
          msg: "${Strings.clientError}, Terjadi kendala pada koneksi, silakan cek kembali koneksi internet anda. Err: ${e.message}",
        ),
      );
    } catch (e) {
      return HttpResponseApi(
        succes: false,
        msg: "${Strings.serverError}, $e",
        apiResponse: ApiResponse(
          error: true,
          msg: "${Strings.serverError}, $e",
        ),
      );
    }
  }
}

class HttpResponseApi {
  bool succes;
  String msg;
  int? code;
  dynamic jsonObject;
  ApiResponse?
      apiResponse; // ini untuk yang gagal saja agar tidak redundant ketika terjadi error

  HttpResponseApi({
    required this.succes,
    required this.msg,
    this.code,
    this.jsonObject,
    this.apiResponse,
  });
}

class ApiResponse {
  bool error;
  String msg;
  dynamic data;
  String code;

  ApiResponse({
    required this.error,
    required this.msg,
    this.data,
    this.code = "",
  });
}