import { describe, it, expect } from 'vitest';
import {
  GetAvailabilityParamsSchema,
  GetInStoreAvailabilityParamsSchema,
  GetPickupAvailabilityParamsSchema,
  GetDeliveryAvailabilityParamsSchema,
  GetDigDeliveryAvailabilityParamsSchema,
  GetB2bDeliveryAvailabilityParamsSchema,
  GetDownloadAvailabilityParamsSchema,
} from './get-availability-params.schema';

describe('GetAvailabilityParamsSchema', () => {
  describe('GetInStoreAvailabilityParamsSchema', () => {
    it('should accept valid in-store params', () => {
      const validParams = {
        orderType: 'Rücklage' as const,
        branchId: 42,
        itemsIds: [123, 456],
      };

      const result = GetInStoreAvailabilityParamsSchema.parse(validParams);
      expect(result).toEqual(validParams);
    });

    it('should coerce string branchId to number', () => {
      const params = {
        orderType: 'Rücklage' as const,
        branchId: '42' as any,
        itemsIds: [123],
      };

      const result = GetInStoreAvailabilityParamsSchema.parse(params);
      expect(result.branchId).toBe(42);
    });

    it('should require itemsIds for in-store', () => {
      const invalidParams = {
        orderType: 'Rücklage' as const,
        branchId: 42,
      };

      expect(() => GetInStoreAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });

    it('should accept multiple itemIds', () => {
      const params = {
        orderType: 'Rücklage' as const,
        branchId: 42,
        itemsIds: [123, 456, 789],
      };

      const result = GetInStoreAvailabilityParamsSchema.parse(params);
      expect(result.itemsIds).toHaveLength(3);
    });

    it('should reject negative branchId', () => {
      const invalidParams = {
        orderType: 'Rücklage' as const,
        branchId: -1,
        itemsIds: [123],
      };

      expect(() => GetInStoreAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });

    it('should reject empty itemsIds array', () => {
      const invalidParams = {
        orderType: 'Rücklage' as const,
        branchId: 42,
        itemsIds: [],
      };

      expect(() => GetInStoreAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });
  });

  describe('GetPickupAvailabilityParamsSchema', () => {
    it('should accept valid pickup params', () => {
      const validParams = {
        orderType: 'Abholung' as const,
        branchId: 42,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
            quantity: 1,
          },
        ],
      };

      const result = GetPickupAvailabilityParamsSchema.parse(validParams);
      expect(result).toEqual(validParams);
    });

    it('should require branchId for pickup', () => {
      const invalidParams = {
        orderType: 'Abholung' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetPickupAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });
  });

  describe('GetDeliveryAvailabilityParamsSchema', () => {
    it('should accept valid delivery params', () => {
      const validParams = {
        orderType: 'Versand' as const,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
            quantity: 3,
          },
        ],
      };

      const result = GetDeliveryAvailabilityParamsSchema.parse(validParams);
      expect(result).toEqual(validParams);
    });

    it('should not require shopId for delivery', () => {
      const validParams = {
        orderType: 'Versand' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetDeliveryAvailabilityParamsSchema.parse(validParams)).not.toThrow();
    });

    it('should coerce string itemId to number', () => {
      const params = {
        orderType: 'Versand' as const,
        items: [{ itemId: '123' as any, ean: '1234567890', quantity: 1 }],
      };

      const result = GetDeliveryAvailabilityParamsSchema.parse(params);
      expect(result.items[0].itemId).toBe(123);
    });

    it('should coerce string quantity to number', () => {
      const params = {
        orderType: 'Versand' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: '5' as any }],
      };

      const result = GetDeliveryAvailabilityParamsSchema.parse(params);
      expect(result.items[0].quantity).toBe(5);
    });

    it('should reject negative quantity', () => {
      const invalidParams = {
        orderType: 'Versand' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: -1 }],
      };

      expect(() => GetDeliveryAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });
  });

  describe('GetDigDeliveryAvailabilityParamsSchema', () => {
    it('should accept valid DIG delivery params', () => {
      const validParams = {
        orderType: 'DIG-Versand' as const,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
            quantity: 2,
          },
        ],
      };

      const result = GetDigDeliveryAvailabilityParamsSchema.parse(validParams);
      expect(result).toEqual(validParams);
    });

    it('should not require shopId for DIG delivery', () => {
      const validParams = {
        orderType: 'DIG-Versand' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetDigDeliveryAvailabilityParamsSchema.parse(validParams)).not.toThrow();
    });
  });

  describe('GetB2bDeliveryAvailabilityParamsSchema', () => {
    it('should accept valid B2B delivery params', () => {
      const validParams = {
        orderType: 'B2B-Versand' as const,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
            quantity: 1,
          },
        ],
      };

      const result = GetB2bDeliveryAvailabilityParamsSchema.parse(validParams);
      expect(result).toEqual(validParams);
    });

    it('should not require shopId for B2B delivery (uses default branch)', () => {
      const validParams = {
        orderType: 'B2B-Versand' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetB2bDeliveryAvailabilityParamsSchema.parse(validParams)).not.toThrow();
    });
  });

  describe('GetDownloadAvailabilityParamsSchema', () => {
    it('should accept valid download params', () => {
      const validParams = {
        orderType: 'Download' as const,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
          },
        ],
      };

      const result = GetDownloadAvailabilityParamsSchema.parse(validParams);
      expect(result).toEqual(validParams);
    });

    it('should not require quantity for downloads', () => {
      const validParams = {
        orderType: 'Download' as const,
        items: [{ itemId: 123, ean: '1234567890' }],
      };

      expect(() => GetDownloadAvailabilityParamsSchema.parse(validParams)).not.toThrow();
    });

    it('should not require shopId for downloads', () => {
      const validParams = {
        orderType: 'Download' as const,
        items: [{ itemId: 123, ean: '1234567890' }],
      };

      expect(() => GetDownloadAvailabilityParamsSchema.parse(validParams)).not.toThrow();
    });
  });

  describe('GetAvailabilityParamsSchema (Union)', () => {
    it('should accept any valid order type', () => {
      const testCases = [
        { orderType: 'Rücklage' as const, branchId: 42, itemsIds: [123] },
        { orderType: 'Abholung' as const, branchId: 42, items: [{ itemId: 123, ean: '1234567890', quantity: 1 }] },
        { orderType: 'Versand' as const, items: [{ itemId: 123, ean: '1234567890', quantity: 1 }] },
        { orderType: 'DIG-Versand' as const, items: [{ itemId: 123, ean: '1234567890', quantity: 1 }] },
        { orderType: 'B2B-Versand' as const, items: [{ itemId: 123, ean: '1234567890', quantity: 1 }] },
        { orderType: 'Download' as const, items: [{ itemId: 123, ean: '1234567890' }] },
      ];

      for (const params of testCases) {
        expect(() => GetAvailabilityParamsSchema.parse(params)).not.toThrow();
      }
    });

    it('should reject invalid order type', () => {
      const invalidParams = {
        orderType: 'InvalidType',
        items: [{ itemId: 123, ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });
  });

  describe('Price handling', () => {
    it('should accept optional price with value and vat', () => {
      const paramsWithPrice = {
        orderType: 'Versand' as const,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
            quantity: 1,
            price: {
              value: {
                value: 19.99,
                currency: 'EUR',
                currencySymbol: '€',
              },
              vat: {
                value: 3.8,
                inPercent: 19,
                label: '19%',
                vatType: 1,
              },
            },
          },
        ],
      };

      const result = GetDeliveryAvailabilityParamsSchema.parse(paramsWithPrice);
      expect(result.items[0].price).toBeDefined();
      expect(result.items[0].price?.value?.value).toBe(19.99);
    });

    it('should accept params without price', () => {
      const paramsWithoutPrice = {
        orderType: 'Versand' as const,
        items: [
          {
            itemId: 123,
            ean: '1234567890',
            quantity: 1,
          },
        ],
      };

      const result = GetDeliveryAvailabilityParamsSchema.parse(paramsWithoutPrice);
      expect(result.items[0].price).toBeUndefined();
    });
  });

  describe('Multiple items', () => {
    it('should accept multiple items', () => {
      const paramsWithMultipleItems = {
        orderType: 'Versand' as const,
        items: [
          { itemId: 123, ean: '1234567890', quantity: 1 },
          { itemId: 456, ean: '0987654321', quantity: 2 },
          { itemId: 789, ean: '1111111111', quantity: 3 },
        ],
      };

      const result = GetDeliveryAvailabilityParamsSchema.parse(paramsWithMultipleItems);
      expect(result.items).toHaveLength(3);
    });
  });

  describe('Edge cases', () => {
    it('should reject zero itemId', () => {
      const invalidParams = {
        orderType: 'Versand' as const,
        items: [{ itemId: 0, ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetDeliveryAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });

    it('should reject zero quantity', () => {
      const invalidParams = {
        orderType: 'Versand' as const,
        items: [{ itemId: 123, ean: '1234567890', quantity: 0 }],
      };

      expect(() => GetDeliveryAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });

    it('should reject missing ean', () => {
      const invalidParams = {
        orderType: 'Versand' as const,
        items: [{ itemId: 123, quantity: 1 }],
      };

      expect(() => GetDeliveryAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });

    it('should reject missing itemId', () => {
      const invalidParams = {
        orderType: 'Versand' as const,
        items: [{ ean: '1234567890', quantity: 1 }],
      };

      expect(() => GetDeliveryAvailabilityParamsSchema.parse(invalidParams)).toThrow();
    });
  });
});
