import '../domain/product_draft.dart';
import '../domain/publish_status.dart';

/// Maps raw WooCommerce REST API v3 product JSON into [ProductDraft] domain
/// objects.
///
/// Only the fields needed for read-only product retrieval are mapped.
/// See https://woocommerce.github.io/woocommerce-rest-api-docs/#product-properties
class WordPressProductMapper {
  const WordPressProductMapper();

  /// Converts a single WooCommerce product JSON map to a [ProductDraft].
  ProductDraft fromJson(Map<String, dynamic> json) {
    return ProductDraft(
      id: json['id']?.toString() ?? '',
      name: (json['name'] as String?) ?? '',
      description: _stripHtml((json['description'] as String?) ?? ''),
      price: _parsePrice(json['price']),
      sku: (json['sku'] as String?) ?? '',
      category: _firstCategoryName(json['categories']),
      imageUrl: _firstImageUrl(json['images']),
      status: _mapStatus(json['status'] as String?),
      lastModified: _parseDate(json['date_modified'] ?? json['date_created']),
    );
  }

  /// Converts a list of WooCommerce product JSON maps to [ProductDraft]s.
  List<ProductDraft> fromJsonList(List<Map<String, dynamic>> jsonList) {
    return jsonList.map(fromJson).toList();
  }

  /// Converts a [PublishStatus] domain value to the corresponding
  /// WooCommerce REST API status string.
  ///
  /// Only [PublishStatus.draft] and [PublishStatus.published] are supported
  /// in the first pass. Throws [ArgumentError] for unsupported values.
  ///
  /// WooCommerce accepts: `publish`, `draft`, `pending`, `private`, `trash`.
  static String toWooCommerceStatus(PublishStatus status) {
    switch (status) {
      case PublishStatus.draft:
        return 'draft';
      case PublishStatus.published:
        return 'publish';
      case PublishStatus.pendingReview:
      case PublishStatus.unpublished:
        throw ArgumentError.value(
          status,
          'status',
          'Unsupported status for WooCommerce update in the first pass',
        );
    }
  }

  // ── Private helpers ──────────────────────────────────────────────────

  /// Maps the WooCommerce `status` string to our [PublishStatus] enum.
  ///
  /// WooCommerce statuses: `publish`, `draft`, `pending`, `private`, `trash`.
  static PublishStatus _mapStatus(String? status) {
    switch (status) {
      case 'publish':
        return PublishStatus.published;
      case 'draft':
        return PublishStatus.draft;
      case 'pending':
        return PublishStatus.pendingReview;
      case 'private':
      case 'trash':
        return PublishStatus.unpublished;
      default:
        return PublishStatus.draft;
    }
  }

  /// Parses a price value that may arrive as a String or num.
  static double _parsePrice(dynamic value) {
    if (value == null) return 0.0;
    if (value is num) return value.toDouble();
    if (value is String) return double.tryParse(value) ?? 0.0;
    return 0.0;
  }

  /// Extracts the name of the first category, or `'Uncategorized'`.
  ///
  /// WooCommerce returns categories as:
  /// ```json
  /// [{"id": 1, "name": "Bowl Cozies", "slug": "bowl-cozies"}]
  /// ```
  static String _firstCategoryName(dynamic categories) {
    if (categories is List && categories.isNotEmpty) {
      final first = categories.first;
      if (first is Map<String, dynamic>) {
        return (first['name'] as String?) ?? 'Uncategorized';
      }
    }
    return 'Uncategorized';
  }

  /// Extracts the `src` URL of the first product image, or empty string.
  ///
  /// WooCommerce returns images as:
  /// ```json
  /// [{"id": 1, "src": "https://...", "name": "image.jpg", ...}]
  /// ```
  static String _firstImageUrl(dynamic images) {
    if (images is List && images.isNotEmpty) {
      final first = images.first;
      if (first is Map<String, dynamic>) {
        return (first['src'] as String?) ?? '';
      }
    }
    return '';
  }

  /// Parses an ISO 8601 date string, falling back to [DateTime.now].
  static DateTime _parseDate(dynamic value) {
    if (value is String && value.isNotEmpty) {
      return DateTime.tryParse(value) ?? DateTime.now();
    }
    return DateTime.now();
  }

  /// Strips basic HTML tags from a string.
  ///
  /// WooCommerce descriptions often contain `<p>`, `<br>`, etc.
  static String _stripHtml(String html) {
    return html
        .replaceAll(RegExp(r'<[^>]*>'), '')
        .replaceAll('&amp;', '&')
        .replaceAll('&lt;', '<')
        .replaceAll('&gt;', '>')
        .replaceAll('&quot;', '"')
        .replaceAll('&#039;', "'")
        .trim();
  }
}
