import 'package:flutter_test/flutter_test.dart';

import 'package:feature_wordpress/feature_wordpress.dart';

void main() {
  const mapper = WordPressProductMapper();

  /// A minimal WooCommerce product JSON payload with all fields populated.
  Map<String, dynamic> buildProductJson({
    int id = 42,
    String name = 'Floral Bowl Cozy',
    String description = '<p>A beautiful bowl cozy.</p>',
    String price = '12.99',
    String sku = 'BC-FLR-001',
    String status = 'publish',
    String dateModified = '2026-03-28T10:30:00',
    String? dateCreated = '2026-03-20T08:00:00',
    List<Map<String, dynamic>>? categories,
    List<Map<String, dynamic>>? images,
  }) {
    return {
      'id': id,
      'name': name,
      'description': description,
      'price': price,
      'sku': sku,
      'status': status,
      'date_modified': dateModified,
      'date_created': dateCreated,
      'categories':
          categories ??
          [
            {'id': 1, 'name': 'Bowl Cozies', 'slug': 'bowl-cozies'},
          ],
      'images':
          images ??
          [
            {'id': 10, 'src': 'https://example.com/image.jpg', 'name': 'image.jpg'},
          ],
    };
  }

  group('WordPressProductMapper.fromJson', () {
    test('maps id as string', () {
      final draft = mapper.fromJson(buildProductJson(id: 99));
      expect(draft.id, '99');
    });

    test('maps name', () {
      final draft = mapper.fromJson(buildProductJson(name: 'Test Product'));
      expect(draft.name, 'Test Product');
    });

    test('strips HTML from description', () {
      final draft = mapper.fromJson(
        buildProductJson(description: '<p>Hello <strong>world</strong></p>'),
      );
      expect(draft.description, 'Hello world');
    });

    test('decodes HTML entities in description', () {
      final draft = mapper.fromJson(buildProductJson(description: 'Tom &amp; Jerry &lt;3&gt;'));
      expect(draft.description, 'Tom & Jerry <3>');
    });

    test('maps price from string', () {
      final draft = mapper.fromJson(buildProductJson(price: '19.50'));
      expect(draft.price, 19.50);
    });

    test('maps price from null to 0.0', () {
      final json = buildProductJson();
      json['price'] = null;
      final draft = mapper.fromJson(json);
      expect(draft.price, 0.0);
    });

    test('maps sku', () {
      final draft = mapper.fromJson(buildProductJson(sku: 'NL-OCN-003'));
      expect(draft.sku, 'NL-OCN-003');
    });

    test('maps first category name', () {
      final draft = mapper.fromJson(
        buildProductJson(
          categories: [
            {'id': 1, 'name': 'Coasters', 'slug': 'coasters'},
            {'id': 2, 'name': 'Kitchen', 'slug': 'kitchen'},
          ],
        ),
      );
      expect(draft.category, 'Coasters');
    });

    test('defaults to Uncategorized when categories is empty', () {
      final draft = mapper.fromJson(buildProductJson(categories: []));
      expect(draft.category, 'Uncategorized');
    });

    test('defaults to Uncategorized when categories is null', () {
      final json = buildProductJson();
      json['categories'] = null;
      final draft = mapper.fromJson(json);
      expect(draft.category, 'Uncategorized');
    });

    test('maps first image URL', () {
      final draft = mapper.fromJson(
        buildProductJson(
          images: [
            {'id': 1, 'src': 'https://example.com/a.jpg'},
            {'id': 2, 'src': 'https://example.com/b.jpg'},
          ],
        ),
      );
      expect(draft.imageUrl, 'https://example.com/a.jpg');
    });

    test('defaults to empty string when images is empty', () {
      final draft = mapper.fromJson(buildProductJson(images: []));
      expect(draft.imageUrl, '');
    });

    test('maps date_modified', () {
      final draft = mapper.fromJson(buildProductJson(dateModified: '2026-04-01T14:00:00'));
      expect(draft.lastModified, DateTime(2026, 4, 1, 14, 0, 0));
    });

    test('falls back to date_created when date_modified is null', () {
      final json = buildProductJson(dateCreated: '2026-03-15T09:00:00');
      json['date_modified'] = null;
      final draft = mapper.fromJson(json);
      expect(draft.lastModified, DateTime(2026, 3, 15, 9, 0, 0));
    });

    group('status mapping', () {
      test('publish -> PublishStatus.published', () {
        final draft = mapper.fromJson(buildProductJson(status: 'publish'));
        expect(draft.status, PublishStatus.published);
      });

      test('draft -> PublishStatus.draft', () {
        final draft = mapper.fromJson(buildProductJson(status: 'draft'));
        expect(draft.status, PublishStatus.draft);
      });

      test('pending -> PublishStatus.pendingReview', () {
        final draft = mapper.fromJson(buildProductJson(status: 'pending'));
        expect(draft.status, PublishStatus.pendingReview);
      });

      test('private -> PublishStatus.unpublished', () {
        final draft = mapper.fromJson(buildProductJson(status: 'private'));
        expect(draft.status, PublishStatus.unpublished);
      });

      test('trash -> PublishStatus.unpublished', () {
        final draft = mapper.fromJson(buildProductJson(status: 'trash'));
        expect(draft.status, PublishStatus.unpublished);
      });

      test('unknown status defaults to PublishStatus.draft', () {
        final draft = mapper.fromJson(buildProductJson(status: 'future'));
        expect(draft.status, PublishStatus.draft);
      });
    });
  });

  group('WordPressProductMapper.toWooCommerceStatus', () {
    test('draft -> "draft"', () {
      expect(WordPressProductMapper.toWooCommerceStatus(PublishStatus.draft), 'draft');
    });

    test('published -> "publish"', () {
      expect(WordPressProductMapper.toWooCommerceStatus(PublishStatus.published), 'publish');
    });

    test('pendingReview throws ArgumentError', () {
      expect(
        () => WordPressProductMapper.toWooCommerceStatus(PublishStatus.pendingReview),
        throwsA(isA<ArgumentError>()),
      );
    });

    test('unpublished throws ArgumentError', () {
      expect(
        () => WordPressProductMapper.toWooCommerceStatus(PublishStatus.unpublished),
        throwsA(isA<ArgumentError>()),
      );
    });
  });

  group('WordPressProductMapper.fromJsonList', () {
    test('maps a list of JSON objects', () {
      final jsonList = [
        buildProductJson(id: 1, name: 'Product A'),
        buildProductJson(id: 2, name: 'Product B'),
        buildProductJson(id: 3, name: 'Product C'),
      ];

      final drafts = mapper.fromJsonList(jsonList);
      expect(drafts.length, 3);
      expect(drafts[0].name, 'Product A');
      expect(drafts[1].name, 'Product B');
      expect(drafts[2].name, 'Product C');
    });

    test('returns empty list for empty input', () {
      final drafts = mapper.fromJsonList([]);
      expect(drafts, isEmpty);
    });
  });

  group('Edge cases', () {
    test('handles completely empty JSON map gracefully', () {
      final draft = mapper.fromJson(<String, dynamic>{});
      expect(draft.id, '');
      expect(draft.name, '');
      expect(draft.description, '');
      expect(draft.price, 0.0);
      expect(draft.sku, '');
      expect(draft.category, 'Uncategorized');
      expect(draft.imageUrl, '');
      expect(draft.status, PublishStatus.draft);
    });

    test('handles numeric price value', () {
      final json = buildProductJson();
      json['price'] = 25.0;
      final draft = mapper.fromJson(json);
      expect(draft.price, 25.0);
    });

    test('handles integer price value', () {
      final json = buildProductJson();
      json['price'] = 10;
      final draft = mapper.fromJson(json);
      expect(draft.price, 10.0);
    });
  });
}
