import { describe, it, expect } from 'vitest';
import {
  CreatePantryItemSchema,
  UpdatePantryItemSchema,
  TransitionPantryItemSchema,
  BatchTransitionSchema,
  PantryQuerySchema,
  ExpiringQuerySchema,
  WasteStatsQuerySchema,
} from './pantry.schemas.js';

describe('Pantry Schemas', () => {
  describe('CreatePantryItemSchema', () => {
    const valid = {
      productId: 'p1',
      storageLocation: 'fridge',
      quantity: 2,
      unit: 'piece',
    };

    it('accepts valid input', () => {
      expect(CreatePantryItemSchema.parse(valid)).toMatchObject(valid);
    });

    it('accepts all optional fields', () => {
      const full = {
        ...valid,
        purchaseDate: '2024-01-15T00:00:00Z',
        expirationDate: '2024-02-15T00:00:00Z',
        notes: 'Organic',
        purchasePrice: 4.99,
        storeId: 's1',
      };
      expect(CreatePantryItemSchema.parse(full)).toMatchObject(full);
    });

    it('rejects missing productId', () => {
      const { productId: _, ...rest } = valid;
      expect(() => CreatePantryItemSchema.parse(rest)).toThrow();
    });

    it('rejects zero quantity', () => {
      expect(() => CreatePantryItemSchema.parse({ ...valid, quantity: 0 })).toThrow();
    });

    it('rejects negative quantity', () => {
      expect(() => CreatePantryItemSchema.parse({ ...valid, quantity: -1 })).toThrow();
    });

    it('rejects invalid storageLocation', () => {
      expect(() => CreatePantryItemSchema.parse({ ...valid, storageLocation: 'garage' })).toThrow();
    });

    it('rejects negative purchasePrice', () => {
      expect(() => CreatePantryItemSchema.parse({ ...valid, purchasePrice: -1 })).toThrow();
    });
  });

  describe('UpdatePantryItemSchema', () => {
    it('accepts partial update', () => {
      const result = UpdatePantryItemSchema.parse({ quantity: 3 });
      expect(result.quantity).toBe(3);
    });

    it('accepts empty object', () => {
      const result = UpdatePantryItemSchema.parse({});
      expect(result).toEqual({});
    });

    it('rejects invalid storageLocation', () => {
      expect(() => UpdatePantryItemSchema.parse({ storageLocation: 'attic' })).toThrow();
    });
  });

  describe('TransitionPantryItemSchema', () => {
    it('accepts valid transition', () => {
      const result = TransitionPantryItemSchema.parse({ status: 'opened' });
      expect(result.status).toBe('opened');
    });

    it('accepts transition with date and notes', () => {
      const input = {
        status: 'consumed',
        date: '2024-01-15T12:00:00Z',
        notes: 'Used in soup',
      };
      expect(TransitionPantryItemSchema.parse(input)).toMatchObject(input);
    });

    it('rejects sealed status as target', () => {
      expect(() => TransitionPantryItemSchema.parse({ status: 'sealed' })).toThrow();
    });

    it('rejects expired status as target', () => {
      expect(() => TransitionPantryItemSchema.parse({ status: 'expired' })).toThrow();
    });
  });

  describe('BatchTransitionSchema', () => {
    it('accepts valid batch transition', () => {
      const input = {
        itemIds: ['id1', 'id2'],
        status: 'consumed',
      };
      expect(BatchTransitionSchema.parse(input)).toMatchObject(input);
    });

    it('rejects empty itemIds', () => {
      expect(() => BatchTransitionSchema.parse({ itemIds: [], status: 'consumed' })).toThrow();
    });

    it('only allows consumed or discarded', () => {
      expect(() => BatchTransitionSchema.parse({ itemIds: ['id1'], status: 'opened' })).toThrow();
    });
  });

  describe('PantryQuerySchema', () => {
    it('applies defaults', () => {
      const result = PantryQuerySchema.parse({});
      expect(result.limit).toBe(20);
    });

    it('accepts all filters', () => {
      const input = {
        storageLocation: 'fridge',
        status: 'sealed,opened',
        urgency: 'urgent',
        productId: 'p1',
        cursor: 'abc',
        limit: 50,
      };
      expect(PantryQuerySchema.parse(input)).toMatchObject(input);
    });
  });

  describe('ExpiringQuerySchema', () => {
    it('applies defaults', () => {
      const result = ExpiringQuerySchema.parse({});
      expect(result.days).toBe(7);
      expect(result.limit).toBe(20);
    });

    it('rejects days > 365', () => {
      expect(() => ExpiringQuerySchema.parse({ days: 400 })).toThrow();
    });
  });

  describe('WasteStatsQuerySchema', () => {
    it('defaults to month', () => {
      const result = WasteStatsQuerySchema.parse({});
      expect(result.period).toBe('month');
    });

    it('accepts valid periods', () => {
      for (const period of ['week', 'month', 'quarter', 'year']) {
        expect(WasteStatsQuerySchema.parse({ period }).period).toBe(period);
      }
    });

    it('rejects invalid period', () => {
      expect(() => WasteStatsQuerySchema.parse({ period: 'decade' })).toThrow();
    });
  });
});
