import 'dart:convert';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:excelso_attendance/helper/logger.dart';
import 'package:excelso_attendance/helper/pref.dart';
import 'package:excelso_attendance/main.dart';
import 'package:excelso_attendance/models/absent.dart';
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/profile.dart';
import 'package:excelso_attendance/models/shift.dart';
import 'package:excelso_attendance/resource/constanta_string.dart';
import 'package:excelso_attendance/resource/strings.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get_ip_address/get_ip_address.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart' show kIsWeb;

class Api {
  static Future<ApiResponse> getNearestBranch() async {
    String apiUrl = "$baseUrl${endPoint}nearest_branch_list";

    try {
      Map<String, dynamic> data = {
        "brand_code": brandCode,
        "user_lat": getLatitude(),
        "user_long": getLongitude(),
      };
      String bodies = jsonEncode(data);
      dynamic jsonObject = await httpRequest(
          typePost, apiUrl, "getNearestBranch",
          bodies: bodies);
      if (jsonObject == false) {
        return ApiResponse(error: true, msg: Strings.cantConnectToServer);
      } else {
        if (jsonObject['status'] == "ok") {
          List<BranchModel> branchList = [];

          List<dynamic> branchs = jsonObject['data']['branch_list'];
          for (int i = 0; i < branchs.length; i++) {
            branchList.add(
              BranchModel.json(
                branchs[i],
              ),
            );
          }
          ConstantString.outletDistance =
              jsonObject['data']['max_distance'].toString();
          ConstantString.logoUrlHome =
              jsonObject['data']['logo_attendance_home'];
          ConstantString.logoUrlCamera =
              jsonObject['data']['logo_attendance_camera'];
          return ApiResponse(
            error: false,
            msg: Strings.succesGetData,
            data: {
              "distance": jsonObject['data']['max_distance'],
              "branchs": branchList,
            },
          );
        } else {
          return ApiResponse(
            error: true,
            msg: jsonObject['msg'],
          );
        }
      }
    } catch (e) {
      return ApiResponse(error: true, msg: Strings.serverError);
    }
  }

  static Future<ApiResponse> getShiftList() async {
    String apiUrl = "$baseUrl${endPoint}shift_list";

    try {
      Map<String, dynamic> data = {
        "brand_code": brandCode,
      };
      String bodies = jsonEncode(data);
      dynamic jsonObject =
          await httpRequest(typePost, apiUrl, "getShiftList", bodies: bodies);
      if (jsonObject == false) {
        return ApiResponse(error: true, msg: Strings.cantConnectToServer);
      } else {
        if (jsonObject['status'] == "ok") {
          List<ShiftModel> shiftList = [];

          List<dynamic> shift = jsonObject['data']['shift_list'];
          for (int i = 0; i < shift.length; i++) {
            shiftList.add(
              ShiftModel.json(
                shift[i],
              ),
            );
          }
          return ApiResponse(
            error: false,
            msg: Strings.succesGetData,
            data: shiftList,
          );
        } else {
          return ApiResponse(
            error: true,
            msg: jsonObject['msg'],
          );
        }
      }
    } catch (e) {
      return ApiResponse(error: true, msg: Strings.serverError);
    }
  }

  static Future<ApiResponse> getUserProfile(
    String branchId,
    String nik,
  ) async {
    String apiUrl = "$baseUrl${endPoint}profile_user";

    try {
      Map<String, dynamic> data = {
        "branch_id": branchId,
        "nik": nik,
        "brand_code": brandCode,
      };
      String bodies = jsonEncode(data);
      dynamic jsonObject =
          await httpRequest(typePost, apiUrl, "getUserProfile", bodies: bodies);
      if (jsonObject == false) {
        return ApiResponse(error: true, msg: Strings.cantConnectToServer);
      } else {
        if (jsonObject['status'] == "ok") {
          Map<String, dynamic> user = jsonObject['data']['user'];
          return ApiResponse(
            error: false,
            msg: Strings.succesGetData,
            data: ProfileModel.json(user),
          );
        } else {
          return ApiResponse(
            error: true,
            msg: jsonObject['msg'],
          );
        }
      }
    } catch (e) {
      return ApiResponse(error: true, msg: Strings.serverError);
    }
  }

  static Future<ApiResponse> shiftIn(
      String branchId, String nik, String shiftId, String photoBase64,
      {int forceSubmit = 0}) async {
    String apiUrl = "$baseUrl${endPoint}clock_in";
    Position position = await Geolocator.getCurrentPosition();
    IpAddress ipAddress = IpAddress(type: RequestType.json);
    dynamic dataIp = await ipAddress.getIpAddress();
    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
    String userAgent = "";
    if (kIsWeb) {
      WebBrowserInfo browser = await deviceInfo.webBrowserInfo;
      userAgent = browser.userAgent ?? "";
    }
    try {
      Map<String, dynamic> data = {
        "branch_id": branchId,
        "brand_code": brandCode,
        "nik": nik,
        "shift_id": shiftId,
        "user_lat": position.latitude,
        "user_long": position.longitude,
        "photo_base64": "data:image/jpeg;base64,$photoBase64",
        "ip": dataIp['ip'],
        "user_agent": userAgent,
        "forced_submit": forceSubmit,
      };
      String bodies = jsonEncode(data);
      dynamic jsonObject =
          await httpRequest(typePost, apiUrl, "shiftIn", bodies: bodies);
      if (jsonObject == false) {
        return ApiResponse(error: true, msg: Strings.cantConnectToServer);
      } else {
        if (jsonObject['status'] == "ok") {
          // simpan NIK user
          List<String> listAbsentUser = getListAbsentUser();
          int indexList =
              listAbsentUser.indexWhere((element) => element == nik);
          if (indexList == -1) {
            listAbsentUser.add(nik);
            setListAbsentUser(listAbsentUser);
          } else {
            // agar yang terakhir di input selalu yang terbaru pada suggest input NIK
            listAbsentUser.removeAt(indexList);
            listAbsentUser.add(nik);
            setListAbsentUser(listAbsentUser);
          }
          return ApiResponse(
            error: false,
            msg: Strings.succesGetData,
            data: AbsentSuccessModel.json(
              jsonObject['data'],
            ),
          );
        } else {
          return ApiResponse(
            error: true,
            msg: jsonObject['msg'],
            code: jsonObject['code'],
          );
        }
      }
    } catch (e) {
      return ApiResponse(error: true, msg: Strings.serverError);
    }
  }

  static Future<ApiResponse> shiftOut(
      String branchId, String nik, String photoBase64,
      {int forceSubmit = 0}) async {
    String apiUrl = "$baseUrl${endPoint}clock_out";

    Position position = await Geolocator.getCurrentPosition();
    IpAddress ipAddress = IpAddress(type: RequestType.json);
    dynamic dataIp = await ipAddress.getIpAddress();
    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
    String userAgent = "";
    if (kIsWeb) {
      WebBrowserInfo browser = await deviceInfo.webBrowserInfo;
      userAgent = browser.userAgent ?? "";
    }
    try {
      Map<String, dynamic> data = {
        "branch_id": branchId,
        "brand_code": brandCode,
        "nik": nik,
        "user_lat": position.latitude,
        "user_long": position.longitude,
        "photo_base64": photoBase64,
        "ip": dataIp['ip'],
        "user_agent": userAgent,
        "forced_submit": forceSubmit,
      };
      String bodies = jsonEncode(data);
      dynamic jsonObject =
          await httpRequest(typePost, apiUrl, "shiftOut", bodies: bodies);
      if (jsonObject == false) {
        return ApiResponse(error: true, msg: Strings.cantConnectToServer);
      } else {
        if (jsonObject['status'] == "ok") {
          // simpan NIK user
          List<String> listAbsentUser = getListAbsentUser();
          int indexList =
              listAbsentUser.indexWhere((element) => element == nik);
          if (indexList == -1) {
            listAbsentUser.add(nik);
            setListAbsentUser(listAbsentUser);
          }
          return ApiResponse(
            error: false,
            msg: Strings.succesGetData,
            data: AbsentSuccessModel.json(
              jsonObject['data'],
            ),
          );
        } else {
          return ApiResponse(
            error: true,
            msg: jsonObject['msg'],
            code: jsonObject['code'],
          );
        }
      }
    } catch (e) {
      return ApiResponse(error: true, msg: Strings.serverError);
    }
  }
}

int typeGet = 1;
int typePost = 2;

Future<dynamic> httpRequest(int typeRequest, String apiUrl, String namaFungsi,
    {String? bodies = ''}) async {
  int timeOut = 10;
  dynamic apiResult;
  if (typeRequest == typePost) {
    apiResult = await http
        .post(Uri.parse(apiUrl),
            headers: {"Content-Type": "application/json"}, body: bodies)
        .timeout(Duration(seconds: timeOut));
  } else if (typeRequest == typeGet) {
    apiResult = await http.get(
      Uri.parse(apiUrl),
      headers: {"Content-Type": "application/json"},
    ).timeout(Duration(seconds: timeOut));
  } else {
    if (debug) {
      logd('HTTP REQUEST', 'TIPE REQUEST TIDAK VALID');
    }
    return false;
  }
  if (apiResult.statusCode == 200 || apiResult.statusCode == 401) {
    var jsonObject = jsonDecode(apiResult.body);
    return jsonObject;
  } else {
    if (debug) {
      logd('API CLASS ON API.DART, FUNGSI: $namaFungsi, URL : $apiUrl',
          'ERROR CONNECT TO SERVER, RESPONSE CODE : ${apiResult.statusCode}, result: ${apiResult.body}');
    }
    return false;
  }
}

Future<void> sendTotelegram(String teks) async {
  String token = '';
  String chatId = '';
  String apiUrl =
      'https://api.telegram.org/bot$token/sendmessage?chat_id=$chatId&text=$teks&parse_mode=HTML&disable_web_page_preview=true';
  httpRequest(typeGet, apiUrl, "sendTotelegram");
}

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

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