import { describe, expect, it } from 'vitest';
import { CartService } from '../application/cart-service.js';
import type { CartRepository } from '../domain/ports.js';
import type { Cart } from '../domain/cart.js';
import type { PricingServicePort } from '../../pricing/index.js';
import type { InventoryServicePort } from '../../inventory/index.js';

const CART: Cart = {
  id: 'cart-1',
  userId: 'user-1',
  promoCode: null,
  createdAt: new Date('2026-01-01T00:00:00Z'),
  updatedAt: new Date('2026-01-01T00:00:00Z'),
  items: [
    {
      id: 'item-1',
      cartId: 'cart-1',
      productId: 'product-1',
      variantId: 'variant-1',
      quantity: 2,
      createdAt: new Date('2026-01-01T00:00:00Z'),
      updatedAt: new Date('2026-01-01T00:00:00Z'),
    },
  ],
};

const repo: CartRepository = {
  getOrCreate: async () => CART,
  addItem: async () => CART,
  changeQuantity: async () => CART,
  removeItem: async () => ({ ...CART, items: [] }),
  setPromoCode: async (_userId, code) => ({ ...CART, promoCode: code }),
};

const pricing: PricingServicePort = {
  getVariantPrice: async () => undefined,
  setVariantPrice: async () => {
    throw new Error('not needed');
  },
  seedVariantPrice: async () => undefined,
  calculate: async ({ variantId, quantity }) => ({
    variantId,
    quantity,
    currency: 'EUR',
    vatRate: 'general',
    vatBasisPoints: 2100,
    netUnitAmountCents: 1000,
    netSubtotalCents: quantity * 1000,
    vatAmountCents: quantity * 210,
    totalCents: quantity * 1210,
  }),
};

const inventory: InventoryServicePort = {
  checkAvailability: async () => ({ available: true, availableQuantity: 5 }),
  reserve: async () => {
    throw new Error('not needed');
  },
  release: async () => {
    throw new Error('not needed');
  },
  confirm: async () => {
    throw new Error('not needed');
  },
  setAvailable: async () => {
    throw new Error('not needed');
  },
};

describe('CartService', () => {
  it('recalculates totals through PricingService and availability through InventoryService', async () => {
    const view = await new CartService(repo, pricing, inventory).getCart('user-1');

    expect(view.totalCents).toBe(2420);
    expect(view.items[0]).toMatchObject({ available: true, pricing: { netUnitAmountCents: 1000 } });
  });
});
