import { randomUUID } from 'node:crypto';
import type pg from 'pg';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createPool } from '../../infrastructure/db/pool.js';
import {
  getTestDbUrl,
  recreateDatabase,
  runMigrations,
} from '../../infrastructure/db/tests/db-test-support.js';
import {
  createInventoryService,
  DEFAULT_STORE_ID,
  InsufficientStockError,
  type InventoryService,
} from '../../modules/inventory/index.js';

const hasDb = Boolean(process.env.TEST_DATABASE_URL);

describe.skipIf(!hasDb)('inventory flows (real PostgreSQL)', () => {
  const url = hasDb ? getTestDbUrl() : '';
  let pool: pg.Pool;
  let inventory: InventoryService;

  beforeAll(async () => {
    await recreateDatabase(url);
    await runMigrations(url, 'up');
    pool = createPool(url);
    inventory = createInventoryService(pool);
  });

  afterAll(async () => {
    await pool.end();
  });

  it('allows exactly one concurrent reservation for the last unit (AC1)', async () => {
    const variantId = randomUUID();
    await inventory.setAvailable({ variantId, storeId: DEFAULT_STORE_ID, quantity: 1 });

    const attempts = await Promise.allSettled(
      Array.from({ length: 10 }, () =>
        inventory.reserve({ variantId, storeId: DEFAULT_STORE_ID, quantity: 1 }),
      ),
    );

    const fulfilled = attempts.filter((result) => result.status === 'fulfilled');
    const rejected = attempts.filter((result) => result.status === 'rejected');
    expect(fulfilled).toHaveLength(1);
    expect(rejected).toHaveLength(9);
    for (const result of rejected) {
      expect(result.reason).toBeInstanceOf(InsufficientStockError);
    }

    const availability = await inventory.checkAvailability(variantId, DEFAULT_STORE_ID, 1);
    expect(availability).toEqual({ available: false, availableQuantity: 0 });
    const row = await pool.query(
      'SELECT available, reserved, sold, incoming FROM inventory_stock WHERE variant_id = $1',
      [variantId],
    );
    expect(row.rows[0]).toMatchObject({ available: 0, reserved: 1, sold: 0, incoming: 0 });
  });

  it('rejects zero-stock reservations and never makes stock negative (AC2)', async () => {
    const variantId = randomUUID();
    await inventory.setAvailable({ variantId, storeId: DEFAULT_STORE_ID, quantity: 0 });

    await expect(
      inventory.reserve({ variantId, storeId: DEFAULT_STORE_ID, quantity: 1 }),
    ).rejects.toBeInstanceOf(InsufficientStockError);

    const row = await pool.query(
      'SELECT available, reserved, sold, incoming FROM inventory_stock WHERE variant_id = $1',
      [variantId],
    );
    expect(row.rows[0]).toMatchObject({ available: 0, reserved: 0, sold: 0, incoming: 0 });
  });

  it('exposes checkAvailability through the public InventoryService interface (AC4)', async () => {
    const variantId = randomUUID();
    await inventory.setAvailable({ variantId, storeId: DEFAULT_STORE_ID, quantity: 3 });

    await expect(inventory.checkAvailability(variantId, DEFAULT_STORE_ID, 2)).resolves.toEqual({
      available: true,
      availableQuantity: 3,
    });
  });
});
