import { beforeEach, describe, expect, it, vi } from 'vitest'

vi.mock('../../lib/prisma', () => ({
  prisma: {
    vehicle: {
      findMany: vi.fn(),
      count: vi.fn(),
      findFirst: vi.fn(),
      create: vi.fn(),
      update: vi.fn(),
      updateMany: vi.fn(),
    },
    reservation: { findMany: vi.fn() },
    vehicleCalendarBlock: { findMany: vi.fn(), create: vi.fn(), deleteMany: vi.fn() },
    maintenanceLog: { findMany: vi.fn(), create: vi.fn() },
    vehiclePricingConfiguration: { findUnique: vi.fn(), create: vi.fn(), update: vi.fn() },
    vehiclePricingRule: { findFirst: vi.fn(), create: vi.fn(), update: vi.fn(), deleteMany: vi.fn() },
    vehiclePriceHistory: { create: vi.fn() },
  },
}))

import { prisma } from '../../lib/prisma'
import * as repo from './vehicle.repo'

describe('vehicle.repo edge queries', () => {
  beforeEach(() => vi.clearAllMocks())

  it('soft deletes by taking the vehicle out of service and unpublishing it inside the tenant boundary', async () => {
    await repo.softDelete('vehicle_1', 'company_1')

    expect(prisma.vehicle.updateMany).toHaveBeenCalledWith({
      where: { id: 'vehicle_1', companyId: 'company_1' },
      data: { status: 'OUT_OF_SERVICE', isPublished: false },
    })
  })

  it('publishes and unpublishes inside the tenant boundary', async () => {
    await repo.setPublished('vehicle_1', 'company_1', true)
    expect(prisma.vehicle.updateMany).toHaveBeenCalledWith({
      where: { id: 'vehicle_1', companyId: 'company_1' },
      data: { isPublished: true },
    })
  })

  it('finds reservation conflicts by overlap and active statuses only', async () => {
    const start = new Date('2026-09-01T00:00:00.000Z')
    const end = new Date('2026-09-07T00:00:00.000Z')

    await repo.findReservationConflicts('vehicle_1', 'company_1', start, end)

    expect(prisma.reservation.findMany).toHaveBeenCalledWith({
      where: {
        vehicleId: 'vehicle_1',
        companyId: 'company_1',
        status: { in: ['CONFIRMED', 'ACTIVE'] },
        startDate: { lt: end },
        endDate: { gt: start },
      },
      select: { id: true, startDate: true, endDate: true, status: true },
    })
  })

  it('loads calendar reservations and blocks in chronological order for the requested range', async () => {
    const rangeStart = new Date('2026-10-01T00:00:00.000Z')
    const rangeEnd = new Date('2026-10-31T23:59:59.000Z')

    await repo.findCalendarEvents('vehicle_1', 'company_1', rangeStart, rangeEnd)

    expect(prisma.reservation.findMany).toHaveBeenCalledWith(expect.objectContaining({
      where: expect.objectContaining({
        vehicleId: 'vehicle_1',
        companyId: 'company_1',
        status: { in: ['DRAFT', 'CONFIRMED', 'ACTIVE'] },
        startDate: { lt: rangeEnd },
        endDate: { gt: rangeStart },
      }),
      orderBy: { startDate: 'asc' },
    }))
    expect(prisma.vehicleCalendarBlock.findMany).toHaveBeenCalledWith({
      where: { vehicleId: 'vehicle_1', startDate: { lt: rangeEnd }, endDate: { gt: rangeStart } },
      orderBy: { startDate: 'asc' },
    })
  })

  it('loads pricing configuration with deterministic rule and history ordering', async () => {
    await repo.findPricingConfiguration('vehicle_1')

    expect(prisma.vehiclePricingConfiguration.findUnique).toHaveBeenCalledWith({
      where: { vehicleId: 'vehicle_1' },
      include: {
        rules: { orderBy: [{ sortOrder: 'asc' }, { startDate: 'asc' }, { createdAt: 'asc' }] },
        history: { orderBy: { createdAt: 'desc' }, take: 20 },
      },
    })
  })
})
