import 'dart:io';

import 'package:adjust_sdk/adjust.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/widgets.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:play_install_referrer/play_install_referrer.dart';
import 'package:shared_preferences/shared_preferences.dart';

class DeviceInfo {
  static const String _spInstallReferrer = "installReferrer";
  static const String _spAdjustAttribution = "adjustAttribution";
  DeviceInfo._();
  static final DeviceInfo I = DeviceInfo._();
  Future<Map<String, dynamic>> deviceInfo() async {
    final Map<String, dynamic> json = {};

    if (!Platform.isAndroid) {
      return json;
    }

    final packageInfo = await PackageInfo.fromPlatform();
    final devicePlugin = DeviceInfoPlugin();
    final androidInfo = await devicePlugin.androidInfo;

    json["packageName"] = packageInfo.packageName;
    json["versionName"] = packageInfo.version;
    json["versionCode"] = packageInfo.buildNumber;
    json["osVersion"] = androidInfo.version.release;
    json["sdkInt"] = androidInfo.version.sdkInt.toString();
    json["brand"] = androidInfo.brand;
    json["model"] = androidInfo.model;
    json["device"] = androidInfo.device;

    try {
      final results = await Future.wait<String?>([
        getInstallReferrer(),
        getAdjustAdId(),
        getAdjustAttribution(),
      ]);

      final installReferrer = results[0];
      final adid = results[1];
      final adjustAttributionJson = results[2];

      if (installReferrer != null && installReferrer.isNotEmpty) {
        json["installReferrer"] = installReferrer;
      }

      if (adid != null && adid.isNotEmpty) {
        json["adjustAdId"] = adid;
      }

      if (adjustAttributionJson != null && adjustAttributionJson.isNotEmpty) {
        json["adjustInstall"] = adjustAttributionJson;
      }
    } catch (e) {
      debugPrint("[DeviceInfo] load adjust/referrer failed: $e");
    }

    return json;
  }

  Future<String?> getInstallReferrer() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final cachedReferrer = prefs.getString(_spInstallReferrer);
      if (cachedReferrer != null && cachedReferrer.isNotEmpty) {
        return cachedReferrer;
      }

      final referrerDetails = await PlayInstallReferrer.installReferrer;
      final referrer = referrerDetails.installReferrer;

      if (referrer != null && referrer.isNotEmpty) {
        await prefs.setString(_spInstallReferrer, referrer);
      }
      return referrer;
    } catch (e) {
      debugPrint("[DeviceInfo] get install referrer failed: $e");
      return null;
    }
  }

  Future<String?> getAdjustAdId() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final cached = prefs.getString("adjustAdId");
      if (cached != null && cached.isNotEmpty) {
        return cached;
      }

      final adid = await Adjust.getAdidWithTimeout(2000);
      if (adid != null && adid.isNotEmpty) {
        await prefs.setString("adjustAdId", adid);
      }
      return adid;
    } catch (e) {
      debugPrint("[DeviceInfo] get adjust adid failed: $e");
      return null;
    }
  }

  Future<String?> getAdjustAttribution() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final cachedAttribution = prefs.getString(_spAdjustAttribution);
      if (cachedAttribution != null && cachedAttribution.isNotEmpty) {
        return cachedAttribution;
      }

      final attribution = await Adjust.getAttributionWithTimeout(2000);
      final attributionJson = attribution?.jsonResponse;

      if (attributionJson != null && attributionJson.isNotEmpty) {
        await prefs.setString(_spAdjustAttribution, attributionJson);
      }
      return attributionJson;
    } catch (e) {
      debugPrint("[DeviceInfo] get adjust attribution failed: $e");
      return null;
    }
  }
}
