import 'dart:convert';
import 'package:aman_kassa_flutter/core/base/base_service.dart';
import 'package:aman_kassa_flutter/core/locator.dart';
import 'package:aman_kassa_flutter/core/models/halyk/close_day_data.dart';
import 'package:aman_kassa_flutter/core/models/halyk/halyk_close_day_dao.dart' as Cd;
import 'package:aman_kassa_flutter/core/models/halyk/halyk_post_session.dart' as Ps;
import 'package:aman_kassa_flutter/core/models/halyk/halyk_response_dao.dart';
import 'package:aman_kassa_flutter/core/models/transaction_item.dart';
import 'package:aman_kassa_flutter/core/services/ApiService.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';

import '../models/aman_dao.dart';


class BankService extends BaseService {
  int sdkVersion = 27;
  String packageName = 'ru.m4bank.softpos.halyk';
  final ApiService _api = locator<ApiService>();
  final MethodChannel _channel = MethodChannel('channel:com.amanKassa/bank');


  Future<int> version() async {
    String result;
    try {
      result = await _channel.invokeMethod('version');
    } catch (e, stack) {
      log.e("BankService", e, stack);
      result = '0';
    }
    log.i(result);
    return int.parse(result);
  }

  Future<Ps.HalykPosSession?> renewToken({required String token, required String login, required String password}) async {
    Ps.HalykPosSession? result;
    try {
      result  = await _api.halykPosToken(token, login, password);
    } catch (e, stack) {
      log.e("BankService", e, stack);
    }
    return result;
  }



  Future<Cd.HalykCloseDayDao?> closeDay({ required String token}) async {
    try {
      String response = await _channel.invokeMethod("closeDay", <String, dynamic>{
        'token': token,
        'packageName': packageName
      });
      log.i(response);
      Cd.HalykCloseDayDao dao = Cd.HalykCloseDayDao.fromMap(json.decode(response))!;
      return dao;
    } catch (e, stack) {
      log.e("BankService", e, stack);
      return new Cd.HalykCloseDayDao(result: Cd.ResultBean(description: 'Ошибка при закрытии дня', code: -1));
    }
  }

  Future<HalykResponse> pay({required double amount, required String token}) async {
    try {

      double total = amount * 100;
      log.i('total: $total, ${total.toInt()}');
      String response = await _channel.invokeMethod("pay", <String, dynamic>{
        'amount': total.toInt(),
        'token': token,
        'packageName': packageName
      });
      log.i(response);
      HalykResponse dao = HalykResponse.fromMap(json.decode(response))!;
      return dao;
    } catch (e, stack) {
      log.e("BankService", e, stack);
      return new HalykResponse(result: ResultBean(description: 'Ошибка оплаты', code: -1));
    }
  }

  Future<HalykResponse> refund({required double amount, required String token, required int terminalId, required int operDay, required int transNum }) async {
    try {
      String response = await _channel.invokeMethod("refund", <String, dynamic>{
        'amount': amount.toInt(),
        'token': token,
        'terminalId': terminalId,
        'operDay': operDay,
        'transNum': transNum,
        'packageName': packageName
      });
      HalykResponse dao = HalykResponse.fromMap(json.decode(response))!;
      return dao;
    } catch (e, stack) {
      log.e("BankService", e, stack);
      return new HalykResponse(result: ResultBean(description: 'Ошибка при возврате', code: -1));
    }
  }

  Future<HalykResponse> reversal({ required String token, required int terminalId, required int operDay, required int transNum }) async {
    try {
      String response = await _channel.invokeMethod("reversal", <String, dynamic>{
         'token': token,
        'terminalId': terminalId,
        'operDay': operDay,
        'transNum': transNum,
        'packageName': packageName
      });
      log.i(response);
      HalykResponse dao = HalykResponse.fromMap(json.decode(response))!;
      return dao;
    } catch (e, stack) {
      log.e("BankService", e, stack);
      return new HalykResponse(result: ResultBean(description: 'Ошибка при возврате', code: -1));
    }
  }


  CloseDayData closeDayDataConvert(Cd.TransactionsBean transactions) {
    final DateFormat formatter = DateFormat('dd.MM.yyyy');
    final DateTime now = DateTime.now();
    final String formatted = formatter.format(now);
    List<Cd.TransactionBean> items = transactions.transaction!;
    num totalAmount = 0;
    int totalCount = 0;
    num paymentAmount = 0;
    int paymentCount = 0;
    num refundAmount = 0;
    int refundCount = 0;
    num cancelAmount = 0;
    int cancelCount = 0;

    for(Cd.TransactionBean item in items) {
      if(item.type == 'PAYMENT') {
        paymentCount++;
        paymentAmount += ( item.amount / 100 );
        totalAmount += ( item.amount / 100 );
      } else if(item.type == 'REFUND') {
        refundCount++;
        refundAmount += ( item.amount / 100 );
        totalAmount -= ( item.amount / 100 );
      } else if(item.type == 'REVERSAL') {
        cancelCount++;
        cancelAmount += ( item.amount / 100 );
        totalAmount -= ( item.amount / 100 );
      }
      totalCount++;
    }

    CloseDayData closeDayData = new CloseDayData(
        items: items,
        title: 'Отчет POS от $formatted',
        totalAmount: totalAmount, totalCount: totalCount,
        paymentAmount: paymentAmount, paymentCount: paymentCount,
        refundAmount: refundAmount, refundCount: refundCount,
        cancelAmount: cancelAmount, cancelCount: cancelCount,
    );
    return closeDayData;
  }

}
