import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mnemo_cards/managers/repository/repository.dart';
import 'package:mnemo_cards/managers/user_manager.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:package_info_plus/package_info_plus.dart';

import '../../features/purchase/in_app_purchase.dart';
import '../../main.dart';
import 'api.dart';
import 'firebase_config_repository.dart';

class HttpRepository extends Repository with Api {
  final Dio _dio;

  HttpRepository(this._dio);

  @override
  Future<List<Map<String, Object?>>> getPacks(
      Map<String, String?>? packData) async {
    final r = await _dio.get<String>(
      '$path/packs/',
      queryParameters: packData,
    );
    final ll =
        (jsonDecode(r.data!) as List<dynamic>).cast<Map<String, Object?>>();
    return ll;
  }

  @override
  Future<UserDto> get user async => UserDto.empty;

  @override
  Stream<UserDto> get userStream =>
      Stream.periodic(const Duration(seconds: 5)).map((event) => UserDto.empty);

  @override
  Future<void> updateUser(UserDto dto) async {}

  @override
  Future<(UserDto, String)> createOrGetUser(
    String externalId,
    ExternalIdType idType,
    String? name,
  ) async {
    final r = await _dio.post<String>('$path/user/create', data: {
      'token': externalId,
      'tokenType': idType.name,
      'name': name,
    }).catchError(
        (error, stackTrace) => log('', error: error, stackTrace: stackTrace));
    //todo add client header encryption ??
    final authToken = r.headers[HttpHeaders.authorizationHeader]!.last;
    return (
      UserDto.fromJson(
        jsonDecode(r.data as String) as Map<String, Object?>,
      ),
      authToken,
    );
  }

  void setAuthToken(String? authToken) {
    _dio.interceptors.add(
      InterceptorsWrapper(onRequest: (options, handler) {
        options.headers[HttpHeaders.authorizationHeader] = authToken;
        handler.next(options);
      }),
    );
  }

  @override
  Future<UserDto?> getUser() async {
    final r = await _dio.get<String>('$path/user');
    if (r.statusCode == 200) {
      return UserDto.fromJson(
        jsonDecode(r.data as String) as Map<String, Object?>,
      );
    }
    return null;
  }

  @override
  Future<void> updateUserData(String id, Map<String, Object?> data) async {}

  @override
  Future<List<Map<String, Object?>>> getTests({String packId = ''}) async {
    final r = await _dio.get<String>(
      '$path/tests/$packId',
    );
    final ll =
        (jsonDecode(r.data!) as List<dynamic>).cast<Map<String, Object?>>();
    return ll;
  }

  @override
  Future<TestDto?> getTest(String id) async {
    final r = await _dio.get<String>(
      '$path/test/$id',
    );
    try {
      return TestDto.fromJson(
        jsonDecode(r.data as String) as Map<String, Object?>,
      );
    } catch (e, s) {
      log(e.toString(), stackTrace: s);
      return null;
    }
  }

  @override
  Future<bool> checkPayment(
    String itemId,
    String key,
    PaymentSystem paymentSystem,
  ) async {
    final r = await _dio.get<String>(
      '$path/check_payment/',
      queryParameters: {
        'id': itemId,
        'token': key,
        'system': paymentSystem.name,
      },
    );
    return jsonDecode(r.data ?? '{}')['result'] ?? false;
  }

  @override
  Future<bool> checkUserPayment() async {
    final r = await _dio.get<String>('$path/check_payments/');
    final result = jsonDecode(r.data ?? '{}')?['result'] ?? false;
    return result;
  }

  Future<String?> createPayment(String id, PaymentSystem paymentSystem) async {
    final r = await _dio.get(
      '$path/create_payment/',
      queryParameters: {
        'id': id,
        'system': paymentSystem.name,
      },
    );
    return jsonDecode(r.data)?['url'] as String?;
  }
}
