import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/main.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/new_views/pages/login_page.dart';

class ApiManager {
  ApiManager._();

  Map<String, String> get _headers => {
        'Content-Type': 'application/json',
        'X-Timezone-Offset': DateTime.now().timeZoneOffset.toString().split(".").first,
        if (user != null) 'Authorization': 'Bearer ${user!.token}',
        if (assetGroup != null) 'AssetGroup': assetGroup!.id.toString(),
      };

  static ApiManager instance = ApiManager._();

  User? user;
  AssetGroup? assetGroup;

  Future<http.Response> get(String url, {Map<String, String>? headers, bool enableToastMessage = true}) async {
    headers ??= {};
    headers.addAll(_headers);
    Uri url0 = Uri.parse(url);
    http.Response response = await http.get(url0, headers: headers);

    try {
      if (response.statusCode == 401) {
        showLoginDialog();
      } else {
        if (jsonDecode(response.body) is Map<String, dynamic>) {
          final message = jsonDecode(response.body)["message"];
          if (message != null && message.toString().isNotEmpty) {
            Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
          }
        }
      }
    } catch (ex) {}

    return response;
  }

  Future<http.Response> post(String url, {Map<String, String>? headers, required Map<String, dynamic> body, bool showToast = true}) async {
    headers ??= {};

    headers.addAll(_headers);

    Uri url0 = Uri.parse(url);
    if (!kReleaseMode) {
      print("URL:$url0");
      print("Headers:$headers");
      print("Body:$body");
    }

    var request = http.Request('POST', url0);
    request.body = json.encode(body);
    request.headers.addAll(headers);

    http.StreamedResponse streamedResponse = await request.send();
    http.Response response = await http.Response.fromStream(streamedResponse);
    try {
      if (response.statusCode == 401) {
        showLoginDialog();
      } else {
        if (jsonDecode(response.body) is Map<String, dynamic>) {
          final message = jsonDecode(response.body)["message"];
          if (message != null && message.toString().isNotEmpty && showToast) {
            Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
          }
        }
      }
    } catch (ex) {}

    return response;
  }

  Future<http.Response> delete(String url, {Map<String, String>? headers, required Map<String, dynamic> body}) async {
    headers ??= {};

    headers.addAll(_headers);

    Uri url0 = Uri.parse(url);
    if (!kReleaseMode) {
      print("URL:$url0");
      print("Headers:$headers");
      print("Body:$body");
    }

    var request = http.Request('DELETE', url0);
    request.body = json.encode(body);
    request.headers.addAll(headers);

    http.StreamedResponse streamedResponse = await request.send();
    http.Response response = await http.Response.fromStream(streamedResponse);
    try {
      if (response.statusCode == 401) {
        showLoginDialog();
      } else {
        if (jsonDecode(response.body) is Map<String, dynamic>) {
          final message = jsonDecode(response.body)["message"];
          if (message != null && message.toString().isNotEmpty) {
            Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
          }
        }
      }
    } catch (ex) {}

    return response;
  }

  // Future<http.Response> postWithOutBody(String url,  {Map<String, String>? headers,bool showLoading = true}) async {
  //   headers ??= {};
  //
  //   headers.addAll(_headers);
  //
  //   Uri _url = Uri.parse(url);
  //   if (!kReleaseMode) {
  //     print("URL:$_url");
  //     print("Headers:$headers");
  //   }
  //
  //   var request = http.Request('POST', _url);
  //   request.headers.addAll(headers);
  //
  //   http.StreamedResponse _streamedResponse = await request.send();
  //   http.Response response = await http.Response.fromStream(_streamedResponse);
  //   try {
  //     if (response.statusCode == 401) {
  //       showLoginDialog();
  //     } else {
  //       if (jsonDecode(response.body) is Map<String, dynamic>) {
  //         final message = jsonDecode(response.body)["message"];
  //         if (message != null && message.toString().isNotEmpty&&showLoading) {
  //           Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
  //         }
  //       }
  //     }
  //   } catch (ex) {}
  //
  //   return response;
  // }

  Future<http.Response> put(String url, {Map<String, String>? headers, required Map<String, dynamic> body}) async {
    headers ??= {};

    headers.addAll(_headers);

    Uri url0 = Uri.parse(url);
    // print(headers);
    // log(json.encode(body));
    var request = http.Request('PUT', url0);
    request.body = json.encode(body);
    request.headers.addAll(headers);

    http.StreamedResponse streamedResponse = await request.send();
    http.Response response = await http.Response.fromStream(streamedResponse);
    try {
      if (response.statusCode == 401) {
        showLoginDialog();
      } else {
        if (jsonDecode(response.body) is Map<String, dynamic>) {
          final message = jsonDecode(response.body)["message"];
          if (message != null && message.toString().isNotEmpty) {
            Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
          }
        }
      }
    } catch (ex) {}
    return response;
  }

  Future<http.Response> multiPart(String url, {Map<String, String>? headers, required Map<String, String> body, required List<Future<MultipartFile>> files}) async {
    Map<String, String> headers0 = const {
      'Content-Type': 'multipart/form-data',
    };

    headers ??= {};

    headers.addAll(headers0);

    Uri url0 = Uri.parse(url);
    // print(_url);
    // print(_headers);
    // print(json.encode(body));
    var request = http.MultipartRequest('POST', url0);
    request.fields.addAll(body);
    request.headers.addAll(headers0);

    for (var element in files) {
      request.files.add(await element);
    }

    //request.files.addAll(_files);
    // print(request.files);
    http.StreamedResponse streamedResponse = await request.send();
    http.Response response = await http.Response.fromStream(streamedResponse);
    try {
      if (response.statusCode == 401) {
        showLoginDialog();
      } else {
        if (jsonDecode(response.body) is Map<String, dynamic>) {
          final message = jsonDecode(response.body)["message"];
          if (message != null && message.toString().isNotEmpty) {
            Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
          }
        }
      }
    } catch (ex) {}
    return response;
  }

  void showLoginDialog() {
    showDialog(
        context: navigatorKey.currentContext!,
        barrierDismissible: false,
        builder: (_) => Platform.isIOS
            ? CupertinoAlertDialog(
                title: const Text('Session Expired'),
                content: const Text('Login session is expired,\nPlease login.'),
                //actionsAlignment: MainAxisAlignment.center,
                actions: [
                  CupertinoButton(
                    child: const Text("Login"),
                    onPressed: () {
                      logout(navigatorKey.currentContext);
                    },
                  )
                ],
              )
            : AlertDialog(
                title: const Text('Session Expired'),
                content: const Text('Login session is expired,\nPlease login.'),
                actionsAlignment: MainAxisAlignment.center,
                contentPadding: const EdgeInsets.only(left: 24.0, top: 20.0, right: 24.0, bottom: 16.0),
                actions: [
                  FilledButton(
                    child: const Text("Login"),
                    onPressed: () {
                      logout(navigatorKey.currentContext);
                    },
                  )
                ],
              ));
  }

  void logout(context) async {
    await Provider.of<SettingProvider>(context, listen: false).resetSettings();
    Provider.of<UserProvider>(context, listen: false).reset();
    Navigator.pop(context);
    Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
  }
}
