/// Data Formatters for Vietnamese Locale
///
/// Provides formatting utilities for currency, dates, phone numbers,
/// and other data types commonly used in the app.
library;

import 'package:intl/intl.dart';

/// Currency formatter for Vietnamese Dong (VND)
class CurrencyFormatter {
  CurrencyFormatter._();

  /// Format amount as Vietnamese currency (e.g., "100,000 ₫")
  static String format(double amount, {bool showSymbol = true}) {
    final formatter = NumberFormat.currency(
      locale: 'vi_VN',
      symbol: showSymbol ? '₫' : '',
      decimalDigits: 0,
    );
    return formatter.format(amount);
  }

  /// Format amount with custom precision
  static String formatWithDecimals(
    double amount, {
    int decimalDigits = 2,
    bool showSymbol = true,
  }) {
    final formatter = NumberFormat.currency(
      locale: 'vi_VN',
      symbol: showSymbol ? '₫' : '',
      decimalDigits: decimalDigits,
    );
    return formatter.format(amount);
  }

  /// Format as compact currency (e.g., "1.5M ₫")
  static String formatCompact(double amount, {bool showSymbol = true}) {
    final formatter = NumberFormat.compactCurrency(
      locale: 'vi_VN',
      symbol: showSymbol ? '₫' : '',
      decimalDigits: 1,
    );
    return formatter.format(amount);
  }

  /// Parse currency string to double
  static double? parse(String value) {
    try {
      // Remove currency symbol and spaces
      final cleaned = value.replaceAll(RegExp(r'[₫\s,]'), '');
      return double.tryParse(cleaned);
    } catch (e) {
      return null;
    }
  }
}

/// Date and time formatter
class DateFormatter {
  DateFormatter._();

  /// Format date as "dd/MM/yyyy" (Vietnamese format)
  static String formatDate(DateTime date) {
    final formatter = DateFormat('dd/MM/yyyy', 'vi_VN');
    return formatter.format(date);
  }

  /// Format date as "dd-MM-yyyy"
  static String formatDateDash(DateTime date) {
    final formatter = DateFormat('dd-MM-yyyy', 'vi_VN');
    return formatter.format(date);
  }

  /// Format time as "HH:mm"
  static String formatTime(DateTime date) {
    final formatter = DateFormat('HH:mm', 'vi_VN');
    return formatter.format(date);
  }

  /// Format date and time as "dd/MM/yyyy HH:mm"
  static String formatDateTime(DateTime date) {
    final formatter = DateFormat('dd/MM/yyyy HH:mm', 'vi_VN');
    return formatter.format(date);
  }

  /// Format date as "dd/MM/yyyy lúc HH:mm"
  static String formatDateTimeVN(DateTime date) {
    final formatter = DateFormat('dd/MM/yyyy', 'vi_VN');
    final timeFormatter = DateFormat('HH:mm', 'vi_VN');
    return '${formatter.format(date)} lúc ${timeFormatter.format(date)}';
  }

  /// Format as relative time (e.g., "2 giờ trước")
  static String formatRelative(DateTime date) {
    final now = DateTime.now();
    final difference = now.difference(date);

    if (difference.inSeconds < 60) {
      return 'Vừa xong';
    } else if (difference.inMinutes < 60) {
      return '${difference.inMinutes} phút trước';
    } else if (difference.inHours < 24) {
      return '${difference.inHours} giờ trước';
    } else if (difference.inDays < 7) {
      return '${difference.inDays} ngày trước';
    } else if (difference.inDays < 30) {
      final weeks = (difference.inDays / 7).floor();
      return '$weeks tuần trước';
    } else if (difference.inDays < 365) {
      final months = (difference.inDays / 30).floor();
      return '$months tháng trước';
    } else {
      final years = (difference.inDays / 365).floor();
      return '$years năm trước';
    }
  }

  /// Format as day of week (e.g., "Thứ Hai")
  static String formatDayOfWeek(DateTime date) {
    final formatter = DateFormat('EEEE', 'vi_VN');
    return formatter.format(date);
  }

  /// Format as month and year (e.g., "Tháng 10 năm 2024")
  static String formatMonthYear(DateTime date) {
    final formatter = DateFormat('MMMM yyyy', 'vi_VN');
    return formatter.format(date);
  }

  /// Format as full date with day of week (e.g., "Thứ Hai, 17/10/2024")
  static String formatFullDate(DateTime date) {
    final dayOfWeek = formatDayOfWeek(date);
    final dateStr = formatDate(date);
    return '$dayOfWeek, $dateStr';
  }

  /// Parse date string in format "dd/MM/yyyy"
  static DateTime? parseDate(String dateStr) {
    try {
      final formatter = DateFormat('dd/MM/yyyy');
      return formatter.parse(dateStr);
    } catch (e) {
      return null;
    }
  }

  /// Parse datetime string in format "dd/MM/yyyy HH:mm"
  static DateTime? parseDateTime(String dateTimeStr) {
    try {
      final formatter = DateFormat('dd/MM/yyyy HH:mm');
      return formatter.parse(dateTimeStr);
    } catch (e) {
      return null;
    }
  }
}

/// Phone number formatter for Vietnamese phone numbers
class PhoneFormatter {
  PhoneFormatter._();

  /// Format phone number as "(0xxx) xxx xxx"
  static String format(String phone) {
    // Remove all non-digit characters
    final cleaned = phone.replaceAll(RegExp(r'\D'), '');

    if (cleaned.isEmpty) return '';

    // Handle Vietnamese phone number formats
    if (cleaned.startsWith('84')) {
      // +84 format
      final local = cleaned.substring(2);
      if (local.length >= 9) {
        return '(+84${local.substring(0, 2)}) ${local.substring(2, 5)} ${local.substring(5)}';
      }
    } else if (cleaned.startsWith('0')) {
      // 0xxx format
      if (cleaned.length >= 10) {
        return '(${cleaned.substring(0, 4)}) ${cleaned.substring(4, 7)} ${cleaned.substring(7)}';
      }
    }

    return phone; // Return original if format doesn't match
  }

  /// Format as international number (+84xxx xxx xxx)
  static String formatInternational(String phone) {
    final cleaned = phone.replaceAll(RegExp(r'\D'), '');

    if (cleaned.isEmpty) return '';

    if (cleaned.startsWith('0')) {
      // Convert 0xxx to +84xxx
      final local = cleaned.substring(1);
      if (local.length >= 9) {
        return '+84${local.substring(0, 2)} ${local.substring(2, 5)} ${local.substring(5)}';
      }
    } else if (cleaned.startsWith('84')) {
      final local = cleaned.substring(2);
      if (local.length >= 9) {
        return '+84${local.substring(0, 2)} ${local.substring(2, 5)} ${local.substring(5)}';
      }
    }

    return phone;
  }

  /// Remove formatting to get clean phone number
  static String clean(String phone) {
    return phone.replaceAll(RegExp(r'\D'), '');
  }

  /// Convert to E.164 format (+84xxxxxxxxx)
  static String toE164(String phone) {
    final cleaned = clean(phone);

    if (cleaned.startsWith('0')) {
      return '+84${cleaned.substring(1)}';
    } else if (cleaned.startsWith('84')) {
      return '+$cleaned';
    } else if (cleaned.startsWith('+84')) {
      return cleaned;
    }

    return '+84$cleaned';
  }

  /// Mask phone number (e.g., "0xxx xxx ***")
  static String mask(String phone) {
    final cleaned = clean(phone);

    if (cleaned.length >= 10) {
      return '${cleaned.substring(0, 4)} ${cleaned.substring(4, 7)} ***';
    }

    return phone;
  }
}

/// Number formatter
class NumberFormatter {
  NumberFormatter._();

  /// Format number with thousand separators
  static String format(num number, {int decimalDigits = 0}) {
    final formatter = NumberFormat('#,###', 'vi_VN');
    if (decimalDigits > 0) {
      return formatter.format(number);
    }
    return formatter.format(number.round());
  }

  /// Format as percentage
  static String formatPercentage(
    double value, {
    int decimalDigits = 0,
    bool showSymbol = true,
  }) {
    final formatter = NumberFormat.percentPattern('vi_VN');
    formatter.maximumFractionDigits = decimalDigits;
    formatter.minimumFractionDigits = decimalDigits;

    final result = formatter.format(value / 100);
    return showSymbol ? result : result.replaceAll('%', '');
  }

  /// Format as compact number (e.g., "1.5K")
  static String formatCompact(num number) {
    final formatter = NumberFormat.compact(locale: 'vi_VN');
    return formatter.format(number);
  }

  /// Format file size
  static String formatBytes(int bytes, {int decimals = 2}) {
    if (bytes <= 0) return '0 B';

    const suffixes = ['B', 'KB', 'MB', 'GB', 'TB'];
    final i = (bytes.bitLength - 1) ~/ 10;
    final value = bytes / (1 << (i * 10));

    return '${value.toStringAsFixed(decimals)} ${suffixes[i]}';
  }

  /// Format duration (e.g., "1:30:45")
  static String formatDuration(Duration duration) {
    final hours = duration.inHours;
    final minutes = duration.inMinutes.remainder(60);
    final seconds = duration.inSeconds.remainder(60);

    if (hours > 0) {
      return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
    } else {
      return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
    }
  }
}

/// Text formatter utilities
class TextFormatter {
  TextFormatter._();

  /// Capitalize first letter
  static String capitalize(String text) {
    if (text.isEmpty) return text;
    return text[0].toUpperCase() + text.substring(1);
  }

  /// Capitalize each word
  static String capitalizeWords(String text) {
    if (text.isEmpty) return text;
    return text.split(' ').map((word) => capitalize(word)).join(' ');
  }

  /// Truncate text with ellipsis
  static String truncate(
    String text,
    int maxLength, {
    String ellipsis = '...',
  }) {
    if (text.length <= maxLength) return text;
    return text.substring(0, maxLength - ellipsis.length) + ellipsis;
  }

  /// Remove diacritics from Vietnamese text
  static String removeDiacritics(String text) {
    const withDiacritics =
        'àáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ';
    const withoutDiacritics =
        'aaaaaaaaaaaaaaaaaeeeeeeeeeeeiiiiioooooooooooooooooouuuuuuuuuuuyyyyyd';

    var result = text.toLowerCase();
    for (var i = 0; i < withDiacritics.length; i++) {
      result = result.replaceAll(withDiacritics[i], withoutDiacritics[i]);
    }

    return result;
  }

  /// Create URL-friendly slug
  static String slugify(String text) {
    var slug = removeDiacritics(text);
    slug = slug.toLowerCase();
    slug = slug.replaceAll(RegExp(r'[^\w\s-]'), '');
    slug = slug.replaceAll(RegExp(r'[-\s]+'), '-');
    return slug;
  }
}

/// Loyalty tier formatter
class LoyaltyFormatter {
  LoyaltyFormatter._();

  /// Format tier name in Vietnamese
  static String formatTier(String tier) {
    switch (tier.toLowerCase()) {
      case 'diamond':
        return 'Kim Cương';
      case 'platinum':
        return 'Bạch Kim';
      case 'gold':
        return 'Vàng';
      default:
        return tier;
    }
  }

  /// Format points with label
  static String formatPoints(int points) {
    return '${NumberFormatter.format(points)} điểm';
  }

  /// Format points progress (e.g., "1,200 / 5,000 điểm")
  static String formatPointsProgress(int current, int target) {
    return '${NumberFormatter.format(current)} / ${NumberFormatter.format(target)} điểm';
  }
}
