/**
 * Integration spec for the price CHECK constraints added in
 * migration 20260420000000_add_price_check_constraints (TEC-2925).
 *
 * Requires a live PostgreSQL test database with the migration applied.
 * Runs under `pnpm --filter api test:integration`.
 */
import { PrismaClient } from '@prisma/client';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';

const prisma = new PrismaClient();

// Use a deterministic, easily-identifiable test fixture so we can clean up.
const TEST_TAG = 'tec-2925-check-constraint-test';

async function createSupportRows() {
  const user = await prisma.user.create({
    data: {
      phone: '+8410000002925',
      passwordHash: 'x',
      fullName: 'TEC-2925 Test',
      role: 'SELLER',
    },
  });
  const property = await prisma.property.create({
    data: {
      title: TEST_TAG,
      description: TEST_TAG,
      propertyType: 'APARTMENT',
      address: TEST_TAG,
      district: 'Q1',
      city: 'HCMC',
      // PostGIS geography column — accept default if optional, otherwise raw SQL
      // is used by other specs; here we rely on the lat/lng fallback.
      areaM2: 50,
    } as any,
  });
  return { user, property };
}

describe('Price CHECK constraints (TEC-2925)', () => {
  let userId: string;
  let propertyId: string;

  beforeAll(async () => {
    const { user, property } = await createSupportRows();
    userId = user.id;
    propertyId = property.id;
  });

  afterAll(async () => {
    await prisma.priceHistory.deleteMany({ where: { listing: { sellerId: userId } } });
    await prisma.listing.deleteMany({ where: { sellerId: userId } });
    await prisma.property.deleteMany({ where: { id: propertyId } });
    await prisma.user.deleteMany({ where: { id: userId } });
    await prisma.$disconnect();
  });

  it('rejects Listing with priceVND = 0', async () => {
    await expect(
      prisma.listing.create({
        data: {
          propertyId,
          sellerId: userId,
          transactionType: 'SALE',
          priceVND: 0n,
        },
      }),
    ).rejects.toThrow(/listing_price_vnd_positive_chk|check constraint/i);
  });

  it('rejects Listing with priceVND < 0', async () => {
    await expect(
      prisma.listing.create({
        data: {
          propertyId,
          sellerId: userId,
          transactionType: 'SALE',
          priceVND: -1n,
        },
      }),
    ).rejects.toThrow(/listing_price_vnd_positive_chk|check constraint/i);
  });

  it('accepts Listing with priceVND > 0', async () => {
    const listing = await prisma.listing.create({
      data: {
        propertyId,
        sellerId: userId,
        transactionType: 'SALE',
        priceVND: 1_000_000_000n,
      },
    });
    expect(listing.priceVND).toBe(1_000_000_000n);
  });

  it('rejects Listing.rentPriceMonthly = 0 (when provided)', async () => {
    await expect(
      prisma.listing.create({
        data: {
          propertyId,
          sellerId: userId,
          transactionType: 'RENT',
          priceVND: 1n,
          rentPriceMonthly: 0n,
        },
      }),
    ).rejects.toThrow(/listing_rent_price_monthly_positive_chk|check constraint/i);
  });

  it('rejects PriceHistory with non-positive prices', async () => {
    const listing = await prisma.listing.create({
      data: {
        propertyId,
        sellerId: userId,
        transactionType: 'SALE',
        priceVND: 5_000_000_000n,
      },
    });
    await expect(
      prisma.priceHistory.create({
        data: { listingId: listing.id, oldPrice: 0n, newPrice: 1n },
      }),
    ).rejects.toThrow(/price_history_old_price_positive_chk|check constraint/i);
    await expect(
      prisma.priceHistory.create({
        data: { listingId: listing.id, oldPrice: 1n, newPrice: -5n },
      }),
    ).rejects.toThrow(/price_history_new_price_positive_chk|check constraint/i);
  });
});
