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

import 'package:aman_kassa_flutter/core/base/base_service.dart';
import 'package:aman_kassa_flutter/core/models/halyk/halyk_post_session.dart';
import 'package:aman_kassa_flutter/core/models/forte/forte_post_session.dart';
import 'package:aman_kassa_flutter/redux/state/user_state.dart';
import 'package:aman_kassa_flutter/redux/store.dart';
import 'package:aman_kassa_flutter/views/login/login_view.dart';
import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:aman_kassa_flutter/core/models/message.dart';
import 'package:aman_kassa_flutter/core/models/response.dart';
import 'package:aman_kassa_flutter/core/models/smena.dart';
import 'package:aman_kassa_flutter/core/route_names.dart';
import 'package:aman_kassa_flutter/core/services/dialog_service.dart';
import 'package:aman_kassa_flutter/core/services/navigator_service.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import '../models/auth_response.dart';

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

/// The service responsible fworking requests
class ApiService extends BaseService {
  static const test_host = 'https://kassa-test.aman.com.kz';
  static const test_endpoint = '$test_host/ru/api/v2';
  static const host = 'https://kassa.aman.com.kz';
  static const endpoint = '$host/ru/api/v2';

  static const pos_endpoint = 'https://partner.aman.com.kz/api';
  final NavigatorService _navigatorService = locator<NavigatorService>();
  final DialogService _dialogService = locator<DialogService>();

  var client = new http.Client();

  bool _test = false;
  bool get test => this._test;
  set test(bool value) => this._test = value;

  Future<AuthBody> authenticate(String email, String password, { bool statusCheck = true}) async {
    Map<String, String> requestBody = <String, String>{
      'email': email,
      'password': password
    };
    String response = await requestFormData('/authenticate', requestBody, statusCheck: statusCheck );
    AuthResponse aman = AuthResponse.fromJson(json.decode(response));
    return aman.body!;
  }

  Future<AuthBody> authenticateToken(String token, { bool statusCheck = true}) async {
    Map<String, String> requestBody = <String, String>{
      'token': token
    };
    String response = await requestFormData('/activate_token', requestBody, statusCheck: statusCheck );
    AuthResponse aman = AuthResponse.fromJson(json.decode(response));
    return aman.body!;
  }

  Future<Response<Message>> isActive(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/test_auth', requestBody, statusCheck: false);
    return Response.fromJson(json.decode(response), Message.fromJson);
  }

  Future<Response<dynamic>> logout(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/logout', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<HalykPosSession> halykPosToken(String token, login, password) async {
    String salt = '!=uF:w1N_Salh?1gVSJ#eGfJYHA(wS4D';
    String hash = md5.convert(utf8.encode('$login$salt')).toString();
    print(hash);

    Map<String, String> requestBody = <String, String>{'login': login, 'hash': hash};
    String pointUrl = test ? '/hb/pos/gettoken' : '/halykpos/gettoken';
    var response = await requestFormData(pointUrl, requestBody, bodyEntry: true, posEndPoint: true, statusCheck: false);
    print(response);
    return HalykPosSession.fromJson(jsonDecode(response));
  }

  Future<FortePosSession> fortePosToken(String token, login, password) async {
    String salt = '!=uF:w1N_Salh?1gVSJ#eGfJYHA(wS4D';
    String hash = md5.convert(utf8.encode('$login$salt')).toString();
    print(hash);

    Map<String, String> requestBody = <String, String>{'login': login, 'hash': hash};
    // String pointUrl = '/fortepos/test/gettoken';
    String pointUrl = '/fortepos/prod/gettoken';
    var response = await requestFormData(pointUrl, requestBody, bodyEntry: true, posEndPoint: true, statusCheck: false);
    print(response);
    return FortePosSession.fromJson(jsonDecode(response));
  }

  Future<Response<dynamic>> money(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/money', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<dynamic>> infoKkm(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/info', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<dynamic>> deposit(String token, String sum) async {
    Map<String, String> requestBody = <String, String>{'api_token': token, 'summ': sum};
    var response = await requestFormData('/deposit', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<dynamic>> withdrawal(String token, String sum) async {
    Map<String, String> requestBody = <String, String>{'api_token': token, 'summ': sum};
    var response = await requestFormData('/withdrawal', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<Smena>> smena(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/smena', requestBody);
    return Response.fromJson(json.decode(response), Smena.fromJson);
  }

  Future<Response<Smena>> closeSmena(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/close_smena', requestBody);
    return Response.fromJson(json.decode(response), Smena.fromJson);
  }

  Future<Response<Smena>> openSmena(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/open_smena', requestBody);
    return Response.fromJson(json.decode(response), Smena.fromJson);
  }

  Future<Response<dynamic>> xReport(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/report_x', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<dynamic>> sell(String token, String checkData) async {
    Map<String, String> requestBody = <String, String>{'api_token': token, 'data': checkData};
    var response = await requestFormData('/sell', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<dynamic>> sellReturn(String token, String checkData, {String? ticketNumber}) async {
    Map<String, String> requestBody = <String, String>{'api_token': token, 'data': checkData};
    if (ticketNumber != null && ticketNumber.isNotEmpty) {
      requestBody['ticketNumber'] = ticketNumber;
    }
    var response = await requestFormData('/sell_return', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }


  Future<String> requestFormData(String point, Map<String, String> requestBody, { bool statusCheck = true, bool bodyEntry = false, bool posEndPoint= false } ) async {
    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();


    Map<String, String> headers = <String, String>{
      HttpHeaders.contentTypeHeader: bodyEntry ? "application/json" : "multipart/form-data",
      HttpHeaders.cacheControlHeader: "no-cache"
    };



    if(Platform.isAndroid) {
      AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
      headers.addAll(<String, String>{
        HttpHeaders.userAgentHeader: androidInfo.model,
        "mob_agent" : "e40c519e7a24d0c93530fd362023afa0",
      });
    }

    if(Platform.isIOS) {
      IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
      headers.addAll(<String, String>{
        HttpHeaders.userAgentHeader: iosInfo.utsname.machine,
        "mob_agent" : "fbd69e994b6251837ba82a08c6f68307",
      });
    }

    String url = '$endpoint$point';
    if(this._test) {
      url = '$test_endpoint$point';
    }
    if(posEndPoint){
      url = '$pos_endpoint$point';
    }
    var uri = Uri.parse(url);

    String body;

    // log.i(uri);
    // log.i(jsonEncode(headers));
    // log.i(jsonEncode(requestBody));

    if(bodyEntry) {
      http.Response res = await http.post(uri, body: jsonEncode(requestBody), headers: headers );
      body = res.body;
    } else {
      var request = http.MultipartRequest('POST', uri)
        ..headers.addAll(headers)
        ..fields.addAll(requestBody);
      var response = await request.send();
      body = await response.stream.bytesToString();
    }



    if(statusCheck) { //Проверка на авторизованный запрос, необязательный параметр
      Response check = Response.fromJsonDynamic(json.decode(body));
      if (!check.operation && ( [401,402,403,412].contains(check.status)  ) ) {

        new Future.delayed(const Duration(milliseconds: 1000), (){
          _dialogService.showDialog(description: 'Необходимо пройти повторную авторизацию');
        UserState state = Redux.store!.state.userState!;
        _navigatorService.replace(LoginViewRoute, arguments: LoginModel(authType: state.authenticateType, login: state.login, password: state.password ));
        });

        
      }
    }
    return body;
  }

  Future<Response<dynamic>> getGoodsFromServer(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/goods', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

  Future<Response<dynamic>> getCategoryFromServer(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/goods_category', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }
  Future<Response<dynamic>> getServiceFromServer(String token) async {
    Map<String, String> requestBody = <String, String>{'api_token': token};
    var response = await requestFormData('/services', requestBody);
    return Response.fromJsonDynamic(json.decode(response));
  }

}
