import { describe, it, expect } from 'vitest';
import {
  analyzeOrderOptions,
  analyzeCustomerTypes,
} from './checkout-analysis.helpers';
import { EntityDTOContainerOfShoppingCartItemDTO } from '@generated/swagger/checkout-api';

describe('Checkout Analysis Helpers', () => {
  describe('analyzeOrderOptions', () => {
    it('should identify take away orders (Rücklage)', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'Rücklage' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasTakeAway).toBe(true);
      expect(result.hasPickUp).toBe(false);
      expect(result.hasDownload).toBe(false);
      expect(result.hasDelivery).toBe(false);
      expect(result.hasDigDelivery).toBe(false);
      expect(result.hasB2BDelivery).toBe(false);
    });

    it('should identify pick up orders (Abholung)', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'Abholung' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasPickUp).toBe(true);
      expect(result.hasTakeAway).toBe(false);
    });

    it('should identify download orders', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'Download' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasDownload).toBe(true);
      expect(result.hasTakeAway).toBe(false);
    });

    it('should identify standard delivery orders (Versand)', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasDelivery).toBe(true);
      expect(result.hasTakeAway).toBe(false);
    });

    it('should identify digital delivery orders (DIG-Versand)', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'DIG-Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasDigDelivery).toBe(true);
      expect(result.hasTakeAway).toBe(false);
    });

    it('should identify B2B delivery orders (B2B-Versand)', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'B2B-Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasB2BDelivery).toBe(true);
      expect(result.hasTakeAway).toBe(false);
    });

    it('should identify multiple order types in the same cart', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 2,
          data: {
            features: { orderType: 'Abholung' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 3,
          data: {
            features: { orderType: 'Download' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasDelivery).toBe(true);
      expect(result.hasPickUp).toBe(true);
      expect(result.hasDownload).toBe(true);
      expect(result.hasTakeAway).toBe(false);
      expect(result.hasDigDelivery).toBe(false);
      expect(result.hasB2BDelivery).toBe(false);
    });

    it('should return false for all flags when items have no orderType feature', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { someOtherFeature: 'value' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasTakeAway).toBe(false);
      expect(result.hasPickUp).toBe(false);
      expect(result.hasDownload).toBe(false);
      expect(result.hasDelivery).toBe(false);
      expect(result.hasDigDelivery).toBe(false);
      expect(result.hasB2BDelivery).toBe(false);
    });

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

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasTakeAway).toBe(false);
      expect(result.hasPickUp).toBe(false);
      expect(result.hasDownload).toBe(false);
      expect(result.hasDelivery).toBe(false);
      expect(result.hasDigDelivery).toBe(false);
      expect(result.hasB2BDelivery).toBe(false);
      expect(result.items).toEqual([]);
    });

    it('should handle items with null/undefined data', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: null,
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 2,
          data: undefined,
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasTakeAway).toBe(false);
      expect(result.hasPickUp).toBe(false);
      expect(result.hasDownload).toBe(false);
      expect(result.hasDelivery).toBe(false);
      expect(result.hasDigDelivery).toBe(false);
      expect(result.hasB2BDelivery).toBe(false);
    });

    it('should handle items with null/undefined features', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: null,
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 2,
          data: {
            features: undefined,
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasTakeAway).toBe(false);
      expect(result.hasPickUp).toBe(false);
    });

    it('should unwrap and include shopping cart items in result', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            productNumber: 'PROD-001',
            features: { orderType: 'Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 2,
          data: {
            productNumber: 'PROD-002',
            features: { orderType: 'Abholung' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.items).toHaveLength(2);
      expect(result.items[0].productNumber).toBe('PROD-001');
      expect(result.items[1].productNumber).toBe('PROD-002');
    });

    it('should handle duplicate order types correctly', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 2,
          data: {
            features: { orderType: 'Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 3,
          data: {
            features: { orderType: 'Versand' },
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      expect(result.hasDelivery).toBe(true);
      expect(result.hasTakeAway).toBe(false);
      expect(result.items).toHaveLength(3);
    });

    it('should handle case-sensitive order type matching', () => {
      // Arrange
      const items: EntityDTOContainerOfShoppingCartItemDTO[] = [
        {
          id: 1,
          data: {
            features: { orderType: 'versand' }, // lowercase
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
        {
          id: 2,
          data: {
            features: { orderType: 'VERSAND' }, // uppercase
          },
        } as EntityDTOContainerOfShoppingCartItemDTO,
      ];

      // Act
      const result = analyzeOrderOptions(items);

      // Assert
      // Should not match due to case sensitivity
      expect(result.hasDelivery).toBe(false);
    });
  });

  describe('analyzeCustomerTypes', () => {
    it('should identify online/webshop customers', () => {
      // Arrange
      const features = { webshop: 'webshop' };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(true);
      expect(result.isGuest).toBe(false);
      expect(result.isB2B).toBe(false);
      expect(result.hasCustomerCard).toBe(false);
      expect(result.isStaff).toBe(false);
    });

    it('should identify guest customers', () => {
      // Arrange
      const features = { guest: 'guest' };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isGuest).toBe(true);
      expect(result.isOnline).toBe(false);
    });

    it('should identify B2B customers', () => {
      // Arrange
      const features = { b2b: 'b2b' };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isB2B).toBe(true);
      expect(result.isOnline).toBe(false);
    });

    it('should identify customers with loyalty cards (Pay4More)', () => {
      // Arrange
      const features = { p4mUser: 'p4mUser' };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.hasCustomerCard).toBe(true);
      expect(result.isOnline).toBe(false);
    });

    it('should identify staff/employee customers', () => {
      // Arrange
      const features = { staff: 'staff' };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isStaff).toBe(true);
      expect(result.isOnline).toBe(false);
    });

    it('should identify multiple customer type features', () => {
      // Arrange
      const features = {
        webshop: 'webshop',
        b2b: 'b2b',
        p4mUser: 'p4mUser',
      };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(true);
      expect(result.isB2B).toBe(true);
      expect(result.hasCustomerCard).toBe(true);
      expect(result.isGuest).toBe(false);
      expect(result.isStaff).toBe(false);
    });

    it('should return all false for empty features object', () => {
      // Arrange
      const features = {};

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(false);
      expect(result.isGuest).toBe(false);
      expect(result.isB2B).toBe(false);
      expect(result.hasCustomerCard).toBe(false);
      expect(result.isStaff).toBe(false);
    });

    it('should handle features with irrelevant keys', () => {
      // Arrange
      const features = {
        someOtherFeature: 'value',
        anotherFeature: 'value',
      };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(false);
      expect(result.isGuest).toBe(false);
      expect(result.isB2B).toBe(false);
      expect(result.hasCustomerCard).toBe(false);
      expect(result.isStaff).toBe(false);
    });

    it('should treat empty string values as falsy', () => {
      // Arrange
      const features = {
        webshop: '',
        guest: '',
        b2b: '',
      };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(false);
      expect(result.isGuest).toBe(false);
      expect(result.isB2B).toBe(false);
    });

    it('should treat any non-empty string value as truthy', () => {
      // Arrange
      const features = {
        webshop: 'yes',
        guest: 'true',
        b2b: '1',
      };

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(true);
      expect(result.isGuest).toBe(true);
      expect(result.isB2B).toBe(true);
    });

    it('should handle null features object safely', () => {
      // Arrange
      const features = null as unknown as Record<string, string>;

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(false);
      expect(result.isGuest).toBe(false);
      expect(result.isB2B).toBe(false);
      expect(result.hasCustomerCard).toBe(false);
      expect(result.isStaff).toBe(false);
    });

    it('should handle undefined features object safely', () => {
      // Arrange
      const features = undefined as unknown as Record<string, string>;

      // Act
      const result = analyzeCustomerTypes(features);

      // Assert
      expect(result.isOnline).toBe(false);
      expect(result.isGuest).toBe(false);
      expect(result.isB2B).toBe(false);
      expect(result.hasCustomerCard).toBe(false);
      expect(result.isStaff).toBe(false);
    });
  });
});
