import 'dart:ui' as ui;
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
import 'dart:io' show Platform;

class DeviceDetails {
  final String? hardwareType; // "Mobile" | "Tablet" | "Desktop" | "Web"
  final String? hardwareModel; // iPhone15,3 | iPad... | Samsung SM-... | ...
  final String? operatingSystem; // "iOS" | "Android" | "macOS" | ...
  final String? osVersion; // "17.6" | "14 (SDK 34)" | ...
  final String? userDeviceName; // iOS: tên máy; Android: fallback
  final String? appVersion; // build-name, ví dụ "3.2.6"
  final String? appBuildNumber; // build-number, ví dụ "326"

  const DeviceDetails({
    this.hardwareType,
    this.hardwareModel,
    this.operatingSystem,
    this.osVersion,
    this.userDeviceName,
    this.appVersion,
    this.appBuildNumber,
  });

  Map<String, String> toMap() => {
    'hardware_type': hardwareType ?? 'Unknown',
    'hardware_model': hardwareModel ?? 'Unknown',
    'operating_system': operatingSystem ?? 'Unknown',
    'os_version': osVersion ?? 'Unknown',
    'user_device_name': userDeviceName ?? 'Unknown',
    'app_version': appVersion ?? 'Unknown',
    'app_build_number': appBuildNumber ?? 'Unknown',
  };

  @override
  String toString() => toMap().toString();
}

class DeviceInfo {
  static const String _deviceIdPreferenceKey = 'device_id';

  static String? _cachedDeviceId;
  static DeviceDetails? _cachedDetails;

  static Future<String> getDeviceId() async {
    // _cachedDeviceId = "13sd26fc-748f-4d1a-a064-af8d7874d565";
    if (_cachedDeviceId != null) return _cachedDeviceId!;
    final prefs = await SharedPreferences.getInstance();
    String? deviceId = prefs.getString(_deviceIdPreferenceKey);
    if (deviceId == null || deviceId.isEmpty) {
      deviceId = const Uuid().v4();
      await prefs.setString(_deviceIdPreferenceKey, deviceId);
    }
    _cachedDeviceId = deviceId;
    return _cachedDeviceId!;
  }

  static Future<DeviceDetails> getDetails() async {
    if (_cachedDetails != null) return _cachedDetails!;

    final deviceInfo = DeviceInfoPlugin();
    final pkg = await PackageInfo.fromPlatform();

    String os = 'Unknown';
    String osVersion = 'Unknown';

    try {
      if (kIsWeb) {
        os = 'Web';
        final web = await deviceInfo.webBrowserInfo;
        final browser = web.browserName.name;
        final appVersion = (web.appVersion ?? '').trim();
        osVersion = appVersion.isEmpty ? browser : '$browser ($appVersion)';
      } else if (Platform.isIOS) {
        os = 'iOS';
        final ios = await deviceInfo.iosInfo;
        osVersion = ios.systemVersion;
      } else if (Platform.isAndroid) {
        os = 'Android';
        final and = await deviceInfo.androidInfo;
        final rel = and.version.release;
        final sdk = and.version.sdkInt.toString() ?? '';
        osVersion = sdk.isEmpty ? rel : '$rel (SDK $sdk)';
      } else {
        os = Platform.operatingSystem;
        osVersion = Platform.operatingSystemVersion;
      }
    } catch (_) {
      // keep defaults
    }

    String hardwareModel = 'Unknown';
    String userDeviceName = 'Unknown';
    bool fallbackIsTablet = false;

    try {
      if (kIsWeb) {
        hardwareModel = 'Browser';
        userDeviceName = 'Web Client';
      } else if (Platform.isIOS) {
        final ios = await deviceInfo.iosInfo;
        hardwareModel = (ios.utsname.machine).trim();
        userDeviceName = (ios.name).trim();
        final modelLower = (ios.model).toLowerCase();
        final machineLower = (ios.utsname.machine).toLowerCase();
        fallbackIsTablet = modelLower.contains('ipad') || machineLower.startsWith('ipad');
      } else if (Platform.isAndroid) {
        final and = await deviceInfo.androidInfo;
        final brand = (and.brand).trim();
        final model = (and.model).trim();
        hardwareModel = [brand, model].where((e) => e.isNotEmpty).join(' ');
        userDeviceName = (and.device).trim().isEmpty ? 'Android Device' : (and.device).trim();
      } else {
        hardwareModel = os;
        userDeviceName = 'Desktop';
      }
    } catch (_) {
      // keep defaults
    }

    final hardwareType = _detectHardwareTypeWithoutContext(
      os: os,
      fallbackIsTablet: fallbackIsTablet,
    );

    _cachedDetails = DeviceDetails(
      hardwareType: hardwareType,
      hardwareModel: hardwareModel,
      operatingSystem: os,
      osVersion: osVersion,
      userDeviceName: userDeviceName,
      appVersion: pkg.version,
      appBuildNumber: pkg.buildNumber,
    );

    return _cachedDetails!;
  }

  /// Không cần BuildContext: dùng kích thước của view đầu tiên từ PlatformDispatcher.
  /// Quy ước: shortestSide >= 600 logical pixels => Tablet.
  static String _detectHardwareTypeWithoutContext({required String os, required bool fallbackIsTablet}) {
    if (os == 'Web') return 'Web';
    if (os != 'iOS' && os != 'Android') return 'Desktop';

    try {
      final views = ui.PlatformDispatcher.instance.views;
      final view = views.isNotEmpty ? views.first : ui.PlatformDispatcher.instance.implicitView;
      if (view != null) {
        final logicalSize = view.physicalSize / view.devicePixelRatio;
        final shortest = logicalSize.shortestSide;
        return shortest >= 600 ? 'Tablet' : 'Mobile';
      }
    } catch (_) {
      // ignore and use fallback
    }
    return fallbackIsTablet ? 'Tablet' : 'Mobile';
  }
}
