import { describe, it, expect } from 'vitest';
import { ShoppingCartItemAdapter } from './shopping-cart-item.adapter';
import { EntityDTOContainerOfShoppingCartItemDTO } from '@generated/swagger/checkout-api';

describe('ShoppingCartItemAdapter', () => {
  describe('toCatalogueFormat', () => {
    it('should convert valid EntityDTOContainer to ShoppingCartItem', () => {
      // Arrange
      const checkoutItem: EntityDTOContainerOfShoppingCartItemDTO = {
        id: 123,
        data: {
          product: {
            ean: '9783123456789',
            catalogProductNumber: '456789', // string
          },
          quantity: 2,
          availability: {
            price: { value: { value: 19.99 } },
            lastRequest: '2025-01-15T10:30:00Z',
          },
          features: { orderType: 'Download' },
        },
      };

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormat(checkoutItem);

      // Assert
      expect(result.id).toBe(123);
      expect(result.data?.product?.ean).toBe('9783123456789');
      expect(result.data?.product?.catalogProductNumber).toBe(456789); // number
      expect(result.data?.quantity).toBe(2);
      expect(result.data?.availability?.price).toBe(19.99);
      expect(result.data?.features?.orderType).toBe('Download');
    });

    it('should throw error when item missing id', () => {
      // Arrange
      const invalidItem: EntityDTOContainerOfShoppingCartItemDTO = {
        // id missing
        data: { product: { ean: '123' } },
      };

      // Act & Assert
      expect(() =>
        ShoppingCartItemAdapter.toCatalogueFormat(invalidItem),
      ).toThrow('Shopping cart item missing required id');
    });

    it('should throw error when item missing data', () => {
      // Arrange
      const invalidItem: EntityDTOContainerOfShoppingCartItemDTO = {
        id: 123,
        // data missing
      };

      // Act & Assert
      expect(() =>
        ShoppingCartItemAdapter.toCatalogueFormat(invalidItem),
      ).toThrow('Shopping cart item missing data property');
    });

    it('should handle missing optional fields gracefully', () => {
      // Arrange
      const minimalItem: EntityDTOContainerOfShoppingCartItemDTO = {
        id: 123,
        data: {},
      };

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormat(minimalItem);

      // Assert
      expect(result.id).toBe(123);
      expect(result.data?.product).toBeUndefined();
      expect(result.data?.quantity).toBeUndefined();
      expect(result.data?.availability).toBeUndefined();
    });

    it('should handle invalid catalogProductNumber', () => {
      // Arrange
      const itemWithInvalidNumber: EntityDTOContainerOfShoppingCartItemDTO = {
        id: 123,
        data: {
          product: {
            ean: '123',
            catalogProductNumber: 'invalid-not-a-number',
          },
        },
      };

      // Act
      const result =
        ShoppingCartItemAdapter.toCatalogueFormat(itemWithInvalidNumber);

      // Assert
      expect(result.data?.product?.catalogProductNumber).toBeUndefined();
    });

    it('should handle missing ean', () => {
      // Arrange
      const itemWithoutEan: EntityDTOContainerOfShoppingCartItemDTO = {
        id: 123,
        data: {
          product: {
            catalogProductNumber: '456',
          },
        },
      };

      // Act
      const result =
        ShoppingCartItemAdapter.toCatalogueFormat(itemWithoutEan);

      // Assert
      expect(result.data?.product?.ean).toBe('');
      expect(result.data?.product?.catalogProductNumber).toBe(456);
    });

    it('should handle nested price structure', () => {
      // Arrange
      const item: EntityDTOContainerOfShoppingCartItemDTO = {
        id: 123,
        data: {
          availability: {
            price: {
              value: {
                value: 29.99,
              },
            },
          },
        },
      };

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormat(item);

      // Assert
      expect(result.data?.availability?.price).toBe(29.99);
    });
  });

  describe('toCatalogueFormatBulk', () => {
    it('should convert array of items, skipping invalid ones', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        { id: 1, data: { product: { ean: '111' } } },
        { id: undefined, data: { product: { ean: '222' } } } as any, // Invalid
        { id: 3, data: { product: { ean: '333' } } },
      ];

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormatBulk(items);

      // Assert
      expect(result).toHaveLength(2);
      expect(result[0].id).toBe(1);
      expect(result[1].id).toBe(3);
    });

    it('should return empty array when all items are invalid', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        { id: undefined, data: {} } as any,
        { data: {} } as any,
      ];

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormatBulk(items);

      // Assert
      expect(result).toHaveLength(0);
    });

    it('should handle empty input array', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [];

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormatBulk(items);

      // Assert
      expect(result).toHaveLength(0);
    });

    it('should convert all valid items successfully', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            product: { ean: '111', catalogProductNumber: '100' },
            quantity: 1,
          },
        },
        {
          id: 2,
          data: {
            product: { ean: '222', catalogProductNumber: '200' },
            quantity: 2,
          },
        },
      ];

      // Act
      const result = ShoppingCartItemAdapter.toCatalogueFormatBulk(items);

      // Assert
      expect(result).toHaveLength(2);
      expect(result[0].data?.product?.catalogProductNumber).toBe(100);
      expect(result[1].data?.product?.catalogProductNumber).toBe(200);
    });
  });

  describe('isValidCatalogueItem', () => {
    it('should return true for valid ShoppingCartItem', () => {
      const validItem = {
        id: 123,
        data: { product: { ean: '123' } },
      };

      expect(ShoppingCartItemAdapter.isValidCatalogueItem(validItem)).toBe(
        true,
      );
    });

    it('should return true for minimal valid item', () => {
      const validItem = {
        id: 123,
      };

      expect(ShoppingCartItemAdapter.isValidCatalogueItem(validItem)).toBe(
        true,
      );
    });

    it('should return false for invalid types', () => {
      expect(ShoppingCartItemAdapter.isValidCatalogueItem(null)).toBe(false);
      expect(ShoppingCartItemAdapter.isValidCatalogueItem(undefined)).toBe(
        false,
      );
      expect(ShoppingCartItemAdapter.isValidCatalogueItem('string')).toBe(
        false,
      );
      expect(
        ShoppingCartItemAdapter.isValidCatalogueItem({ id: 'not-number' }),
      ).toBe(false);
    });

    it('should return false for item without id', () => {
      const invalidItem = {
        data: { product: { ean: '123' } },
      };

      expect(ShoppingCartItemAdapter.isValidCatalogueItem(invalidItem)).toBe(
        false,
      );
    });
  });
});
