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

vi.mock('../../lib/prisma', () => ({ prisma: {} }))
vi.mock('../../lib/redis', () => ({ redis: { on: vi.fn(), get: vi.fn(), set: vi.fn(), del: vi.fn(), quit: vi.fn() } }))
vi.mock('../../modules/site/site.service', () => ({
  getPlatformHomepage: vi.fn(),
  getPlatformPricing: vi.fn(),
  getBrand: vi.fn(),
  getPublicVehicles: vi.fn(),
  getVehicleDetail: vi.fn(),
  getOffers: vi.fn(),
  getBookingOptions: vi.fn(),
  checkAvailability: vi.fn(),
  validatePromoCode: vi.fn(),
  createBooking: vi.fn(),
  getBooking: vi.fn(),
  initPayment: vi.fn(),
  capturePaypal: vi.fn(),
  handleContact: vi.fn(),
}))

import request from 'supertest'
import { createApp } from '../../app'
import * as siteService from '../../modules/site/site.service'

const app = createApp()

describe('site and webhook API boundary contracts', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    vi.mocked(siteService.getPlatformPricing).mockResolvedValue({ prices: { STARTER: { MONTHLY: { MAD: 199 } } }, planFeatures: { STARTER: ['feature'] } } as never)
    vi.mocked(siteService.checkAvailability).mockResolvedValue({ available: true, nextAvailableAt: null } as never)
    vi.mocked(siteService.validatePromoCode).mockResolvedValue({ id: 'offer_1', promoCode: 'SUMMER' } as never)
    vi.mocked(siteService.handleContact).mockResolvedValue({ success: true, deliveredTo: 'hello@example.test' } as never)
  })

  it('keeps removed Clerk webhook endpoint disabled even with raw webhook payloads', async () => {
    const res = await request(app)
      .post('/api/v1/webhooks/clerk')
      .set('content-type', 'application/json')
      .send(JSON.stringify({ type: 'user.created', data: { id: 'user_1' } }))

    expect(res.status).toBe(410)
    expect(res.body).toEqual({
      error: 'disabled',
      message: 'Clerk webhooks are disabled because Clerk has been removed from this project.',
      statusCode: 410,
    })
  })

  it('serves platform pricing without tenant auth', async () => {
    const res = await request(app).get('/api/v1/site/platform/pricing')

    expect(res.status).toBe(200)
    expect(res.body.data.prices.STARTER.MONTHLY.MAD).toBe(199)
    expect(siteService.getPlatformPricing).toHaveBeenCalledWith()
  })

  it('rejects invalid availability ranges before service execution', async () => {
    const res = await request(app).post('/api/v1/site/atlas/availability').send({
      vehicleId: 'vehicle_1',
      startDate: 'not-a-date',
      endDate: '2026-07-10T00:00:00.000Z',
    })

    expect(res.status).toBe(400)
    expect(siteService.checkAvailability).not.toHaveBeenCalled()
  })

  it('normalizes valid availability payloads into service arguments', async () => {
    const res = await request(app).post('/api/v1/site/atlas/availability').send({
      vehicleId: 'cmvehicle000000000000001',
      startDate: '2026-07-01T00:00:00.000Z',
      endDate: '2026-07-10T00:00:00.000Z',
    })

    expect(res.status).toBe(200)
    expect(siteService.checkAvailability).toHaveBeenCalledWith('atlas', 'cmvehicle000000000000001', '2026-07-01T00:00:00.000Z', '2026-07-10T00:00:00.000Z')
  })

  it('rejects empty promo codes and malformed contact emails before public service calls', async () => {
    const promo = await request(app).post('/api/v1/site/atlas/book/validate-code').send({ code: '' })
    expect(promo.status).toBe(400)
    expect(siteService.validatePromoCode).not.toHaveBeenCalled()

    const contact = await request(app).post('/api/v1/site/atlas/contact').send({ name: 'Visitor', email: 'bad-email', message: 'Hello' })
    expect(contact.status).toBe(400)
    expect(siteService.handleContact).not.toHaveBeenCalled()
  })
})
