/// QR Code Generator Utility
///
/// Provides QR code generation functionality for member cards,
/// referral codes, and other QR code use cases.
library;

import 'package:flutter/material.dart';
import 'package:qr_flutter/qr_flutter.dart';

/// QR Code Generator
class QRGenerator {
  QRGenerator._();

  /// Generate QR code widget for member ID
  ///
  /// Used in member cards to display user's member ID as QR code
  static Widget generateMemberQR({
    required String memberId,
    double size = 80.0,
    Color? foregroundColor,
    Color? backgroundColor,
    int version = QrVersions.auto,
    int errorCorrectionLevel = QrErrorCorrectLevel.M,
  }) {
    return QrImageView(
      data: 'MEMBER:$memberId',
      version: version,
      size: size,
      errorCorrectionLevel: errorCorrectionLevel,
      backgroundColor: backgroundColor ?? Colors.white,
      eyeStyle: QrEyeStyle(
        eyeShape: QrEyeShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      dataModuleStyle: QrDataModuleStyle(
        dataModuleShape: QrDataModuleShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      padding: EdgeInsets.zero,
      gapless: true,
    );
  }

  /// Generate QR code widget for referral code
  ///
  /// Used to share referral codes via QR scanning
  static Widget generateReferralQR({
    required String referralCode,
    double size = 200.0,
    Color? foregroundColor,
    Color? backgroundColor,
  }) {
    return QrImageView(
      data: 'REFERRAL:$referralCode',
      version: QrVersions.auto,
      size: size,
      errorCorrectionLevel: QrErrorCorrectLevel.H,
      backgroundColor: backgroundColor ?? Colors.white,
      eyeStyle: QrEyeStyle(
        eyeShape: QrEyeShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      dataModuleStyle: QrDataModuleStyle(
        dataModuleShape: QrDataModuleShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      padding: const EdgeInsets.all(16),
      gapless: true,
      embeddedImageStyle: const QrEmbeddedImageStyle(size: Size(48, 48)),
    );
  }

  /// Generate QR code widget for order tracking
  ///
  /// Used to display order number as QR code for easy tracking
  static Widget generateOrderQR({
    required String orderNumber,
    double size = 150.0,
    Color? foregroundColor,
    Color? backgroundColor,
  }) {
    return QrImageView(
      data: 'ORDER:$orderNumber',
      version: QrVersions.auto,
      size: size,
      errorCorrectionLevel: QrErrorCorrectLevel.M,
      backgroundColor: backgroundColor ?? Colors.white,
      eyeStyle: QrEyeStyle(
        eyeShape: QrEyeShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      dataModuleStyle: QrDataModuleStyle(
        dataModuleShape: QrDataModuleShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      padding: const EdgeInsets.all(12),
      gapless: true,
    );
  }

  /// Generate QR code widget for product info
  ///
  /// Used to encode product SKU or URL for quick access
  static Widget generateProductQR({
    required String productId,
    double size = 120.0,
    Color? foregroundColor,
    Color? backgroundColor,
  }) {
    return QrImageView(
      data: 'PRODUCT:$productId',
      version: QrVersions.auto,
      size: size,
      errorCorrectionLevel: QrErrorCorrectLevel.M,
      backgroundColor: backgroundColor ?? Colors.white,
      eyeStyle: QrEyeStyle(
        eyeShape: QrEyeShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      dataModuleStyle: QrDataModuleStyle(
        dataModuleShape: QrDataModuleShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      padding: const EdgeInsets.all(10),
      gapless: true,
    );
  }

  /// Generate QR code widget with custom data
  ///
  /// Generic QR code generator for any string data
  static Widget generateCustomQR({
    required String data,
    double size = 200.0,
    Color? foregroundColor,
    Color? backgroundColor,
    int errorCorrectionLevel = QrErrorCorrectLevel.M,
    EdgeInsets padding = const EdgeInsets.all(16),
    bool gapless = true,
  }) {
    return QrImageView(
      data: data,
      version: QrVersions.auto,
      size: size,
      errorCorrectionLevel: errorCorrectionLevel,
      backgroundColor: backgroundColor ?? Colors.white,
      eyeStyle: QrEyeStyle(
        eyeShape: QrEyeShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      dataModuleStyle: QrDataModuleStyle(
        dataModuleShape: QrDataModuleShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      padding: padding,
      gapless: gapless,
    );
  }

  /// Generate QR code widget with embedded logo
  ///
  /// Used for branded QR codes with app logo in center
  static Widget generateQRWithLogo({
    required String data,
    required Widget embeddedImage,
    double size = 250.0,
    Color? foregroundColor,
    Color? backgroundColor,
    Size embeddedImageSize = const Size(64, 64),
  }) {
    return QrImageView(
      data: data,
      version: QrVersions.auto,
      size: size,
      errorCorrectionLevel: QrErrorCorrectLevel.H, // High correction for logo
      backgroundColor: backgroundColor ?? Colors.white,
      eyeStyle: QrEyeStyle(
        eyeShape: QrEyeShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      dataModuleStyle: QrDataModuleStyle(
        dataModuleShape: QrDataModuleShape.square,
        color: foregroundColor ?? Colors.black,
      ),
      padding: const EdgeInsets.all(20),
      gapless: true,
      embeddedImage: embeddedImage is AssetImage
          ? (embeddedImage as AssetImage).assetName as ImageProvider
          : null,
      embeddedImageStyle: QrEmbeddedImageStyle(size: embeddedImageSize),
    );
  }

  /// Parse QR code data and extract type and value
  ///
  /// Returns a map with 'type' and 'value' keys
  static Map<String, String>? parseQRData(String data) {
    try {
      if (data.contains(':')) {
        final parts = data.split(':');
        if (parts.length == 2) {
          return {'type': parts[0].toUpperCase(), 'value': parts[1]};
        }
      }

      // If no type prefix, return as generic data
      return {'type': 'GENERIC', 'value': data};
    } catch (e) {
      return null;
    }
  }

  /// Validate QR code data format
  static bool isValidQRData(String data, {String? expectedType}) {
    if (data.isEmpty) return false;

    final parsed = parseQRData(data);
    if (parsed == null) return false;

    if (expectedType != null) {
      return parsed['type'] == expectedType.toUpperCase();
    }

    return true;
  }

  /// Generate QR data string with type prefix
  static String generateQRData(String type, String value) {
    return '${type.toUpperCase()}:$value';
  }
}

/// QR Code Types
class QRCodeType {
  QRCodeType._();

  static const String member = 'MEMBER';
  static const String referral = 'REFERRAL';
  static const String order = 'ORDER';
  static const String product = 'PRODUCT';
  static const String payment = 'PAYMENT';
  static const String url = 'URL';
  static const String generic = 'GENERIC';
}

/// QR Code Scanner Result
class QRScanResult {
  final String type;
  final String value;
  final String rawData;

  const QRScanResult({
    required this.type,
    required this.value,
    required this.rawData,
  });

  /// Check if scan result is of expected type
  bool isType(String expectedType) {
    return type.toUpperCase() == expectedType.toUpperCase();
  }

  /// Check if result is a member QR code
  bool get isMember => isType(QRCodeType.member);

  /// Check if result is a referral QR code
  bool get isReferral => isType(QRCodeType.referral);

  /// Check if result is an order QR code
  bool get isOrder => isType(QRCodeType.order);

  /// Check if result is a product QR code
  bool get isProduct => isType(QRCodeType.product);

  /// Check if result is a URL QR code
  bool get isUrl => isType(QRCodeType.url);

  factory QRScanResult.fromRawData(String rawData) {
    final parsed = QRGenerator.parseQRData(rawData);

    if (parsed != null) {
      return QRScanResult(
        type: parsed['type']!,
        value: parsed['value']!,
        rawData: rawData,
      );
    }

    return QRScanResult(
      type: QRCodeType.generic,
      value: rawData,
      rawData: rawData,
    );
  }

  @override
  String toString() => 'QRScanResult(type: $type, value: $value)';
}
