import { describe, it, expect } from 'vitest';
import {
  AvailabilityAdapter,
  CatalogueAvailabilityResponse,
} from './availability.adapter';

describe('AvailabilityAdapter', () => {
  describe('toCheckoutFormat', () => {
    it('should convert catalogue availability to checkout format', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
      };

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
      );

      // Assert
      expect(result.availabilityType).toBe(2);
      expect(result.ssc).toBe('100'); // Converted to string
      expect(result.sscText).toBe('In Stock');
      expect(result.supplier?.id).toBe(42);
      expect(result.supplier?.data?.id).toBe(42);
      expect(result.isPrebooked).toBe(false);
      expect(result.estimatedShippingDate).toBe('2025-01-20');
      expect(result.price?.value?.value).toBe(29.99);
      expect(result.lastRequest).toBe('2025-01-15T10:00:00Z');
    });

    it('should use original price when provided', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
      };
      const originalPrice = 24.99;

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
        originalPrice,
      );

      // Assert
      expect(result.price?.value?.value).toBe(24.99); // Original price preserved
    });

    it('should include optional logistician when present', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
        logistician: { id: 5 },
      };

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
      );

      // Assert
      expect(result.logistician?.id).toBe(5);
      expect(result.logistician?.data?.id).toBe(5);
    });

    it('should include optional estimated delivery when present', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
        estimatedDelivery: {
          start: '2025-01-20',
          stop: '2025-01-22',
        },
      };

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
      );

      // Assert
      expect(result.estimatedDelivery).toEqual({
        start: '2025-01-20',
        stop: '2025-01-22',
      });
    });

    it('should include optional supplier info when present', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
        supplierProductNumber: 'SUP-12345',
        supplierInfo: 'Fast shipping',
      };

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
      );

      // Assert
      expect(result.supplierProductNumber).toBe('SUP-12345');
      expect(result.supplierInfo).toBe('Fast shipping');
    });

    it('should include inStock when present', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
        inStock: 50,
      };

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
      );

      // Assert
      expect(result.inStock).toBe(50);
    });

    it('should handle zero values correctly', () => {
      // Arrange
      const catalogueAvailability: CatalogueAvailabilityResponse = {
        availabilityType: 0,
        ssc: 0,
        sscText: 'Unavailable',
        supplier: { id: 0 },
        isPrebooked: false,
        estimatedShippingDate: '',
        price: 0,
        lastRequest: '',
        inStock: 0,
      };

      // Act
      const result = AvailabilityAdapter.toCheckoutFormat(
        catalogueAvailability,
      );

      // Assert
      expect(result.availabilityType).toBe(0);
      expect(result.ssc).toBe('0');
      expect(result.price?.value?.value).toBe(0);
      expect(result.inStock).toBe(0);
    });
  });

  describe('isValidCatalogueResponse', () => {
    it('should return true for valid catalogue response', () => {
      const validResponse: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
      };

      expect(
        AvailabilityAdapter.isValidCatalogueResponse(validResponse),
      ).toBe(true);
    });

    it('should return true for response with optional fields', () => {
      const validResponse: CatalogueAvailabilityResponse = {
        availabilityType: 2,
        ssc: 100,
        sscText: 'In Stock',
        supplier: { id: 42 },
        isPrebooked: false,
        estimatedShippingDate: '2025-01-20',
        price: 29.99,
        lastRequest: '2025-01-15T10:00:00Z',
        logistician: { id: 5 },
        inStock: 50,
      };

      expect(
        AvailabilityAdapter.isValidCatalogueResponse(validResponse),
      ).toBe(true);
    });

    it('should return false for invalid types', () => {
      expect(AvailabilityAdapter.isValidCatalogueResponse(null)).toBe(false);
      expect(AvailabilityAdapter.isValidCatalogueResponse(undefined)).toBe(
        false,
      );
      expect(AvailabilityAdapter.isValidCatalogueResponse('string')).toBe(
        false,
      );
      expect(AvailabilityAdapter.isValidCatalogueResponse([])).toBe(false);
    });

    it('should return false for missing required fields', () => {
      const invalidResponses = [
        { ssc: 100, sscText: 'Test', supplier: { id: 1 } }, // Missing availabilityType
        { availabilityType: 2, sscText: 'Test', supplier: { id: 1 } }, // Missing ssc
        { availabilityType: 2, ssc: 100, supplier: { id: 1 } }, // Missing sscText
        { availabilityType: 2, ssc: 100, sscText: 'Test' }, // Missing supplier
      ];

      invalidResponses.forEach((response) => {
        expect(AvailabilityAdapter.isValidCatalogueResponse(response)).toBe(
          false,
        );
      });
    });

    it('should return false for incorrect field types', () => {
      const invalidResponses = [
        {
          availabilityType: 'string',
          ssc: 100,
          sscText: 'Test',
          supplier: { id: 1 },
        },
        {
          availabilityType: 2,
          ssc: 'string',
          sscText: 'Test',
          supplier: { id: 1 },
        },
        { availabilityType: 2, ssc: 100, sscText: 123, supplier: { id: 1 } },
        {
          availabilityType: 2,
          ssc: 100,
          sscText: 'Test',
          supplier: 'invalid',
        },
      ];

      invalidResponses.forEach((response) => {
        expect(AvailabilityAdapter.isValidCatalogueResponse(response)).toBe(
          false,
        );
      });
    });
  });
});
