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

vi.mock('jsonwebtoken', () => ({ default: { verify: vi.fn() } }))
vi.mock('../../lib/redis', () => ({
  redis: { on: vi.fn(), get: vi.fn(), set: vi.fn(), del: vi.fn(), quit: vi.fn() },
}))
vi.mock('../../lib/prisma', () => ({
  prisma: {
    employee: { findUnique: vi.fn() },
    company: { findUnique: vi.fn() },
    subscription: { findUnique: vi.fn() },
  },
}))
vi.mock('../../modules/vehicles/vehicle.service', () => ({
  listVehicles: vi.fn(),
  getVehicle: vi.fn(),
  createVehicle: vi.fn(),
  updateVehicle: vi.fn(),
  deleteVehicle: vi.fn(),
  uploadPhotos: vi.fn(),
  deletePhoto: vi.fn(),
  setStatus: vi.fn(),
  setPublished: vi.fn(),
  checkAvailability: vi.fn(),
  getCalendar: vi.fn(),
  createCalendarBlock: vi.fn(),
  deleteCalendarBlock: vi.fn(),
  getMaintenanceLogs: vi.fn(),
  createMaintenanceLog: vi.fn(),
  getVehiclePricing: vi.fn(),
  updateVehiclePricing: vi.fn(),
  createVehiclePricingRule: vi.fn(),
  updateVehiclePricingRule: vi.fn(),
  deleteVehiclePricingRule: vi.fn(),
}))

import request from 'supertest'
import jwt from 'jsonwebtoken'
import { createApp } from '../../app'
import { prisma } from '../../lib/prisma'
import * as vehicleService from '../../modules/vehicles/vehicle.service'

const app = createApp()

function employee(role = 'MANAGER') {
  return {
    id: 'employee_1',
    role,
    isActive: true,
    companyId: 'company_1',
    company: { id: 'company_1', status: 'ACTIVE' },
  }
}

beforeEach(() => {
  vi.clearAllMocks()
  process.env.JWT_SECRET = 'test-secret'
  vi.mocked(jwt.verify).mockReturnValue({ sub: 'employee_1', type: 'employee' } as never)
  vi.mocked(prisma.employee.findUnique).mockResolvedValue(employee() as never)
  vi.mocked(prisma.company.findUnique).mockResolvedValue({ id: 'company_1', status: 'ACTIVE' } as never)
  vi.mocked(prisma.subscription.findUnique).mockResolvedValue({ status: 'ACTIVE' } as never)
})

describe('vehicle pricing API contracts', () => {
  it('allows active tenants to read vehicle pricing', async () => {
    vi.mocked(vehicleService.getVehiclePricing).mockResolvedValue({
      configuration: { id: 'pricing_config_1', baseDailyRate: 4000 },
      rules: [],
      history: [],
      preview: { today: { dailyRate: 4000 }, next14Days: [] },
    } as never)

    const res = await request(app)
      .get('/api/v1/vehicles/vehicle_1/pricing')
      .set('Authorization', 'Bearer employee-token')

    expect(res.status).toBe(200)
    expect(res.body.data.configuration.id).toBe('pricing_config_1')
    expect(vehicleService.getVehiclePricing).toHaveBeenCalledWith('vehicle_1', 'company_1')
  })

  it('rejects invalid pricing config payloads before updating pricing', async () => {
    const res = await request(app)
      .put('/api/v1/vehicles/vehicle_1/pricing')
      .set('Authorization', 'Bearer employee-token')
      .send({
        pricingMode: 'CHAOS',
        baseDailyRate: -1,
        maxDailyPriceMovementPct: 101,
      })

    expect(res.status).toBe(400)
    expect(vehicleService.updateVehiclePricing).not.toHaveBeenCalled()
  })

  it('passes parsed pricing configuration and employee identity to the service', async () => {
    vi.mocked(vehicleService.updateVehiclePricing).mockResolvedValue({ configuration: { id: 'pricing_config_1' }, rules: [], history: [], preview: {} } as never)

    const payload = {
      pricingMode: 'AUTOMATIC',
      baseDailyRate: 4500,
      weeklyRate: 27000,
      weekendRate: null,
      maxDailyPriceMovementPct: 15,
      automaticPricingEnabled: true,
      approvalRequired: true,
      note: 'Demand change',
    }

    const res = await request(app)
      .put('/api/v1/vehicles/vehicle_1/pricing')
      .set('Authorization', 'Bearer employee-token')
      .send(payload)

    expect(res.status).toBe(200)
    expect(vehicleService.updateVehiclePricing).toHaveBeenCalledWith('vehicle_1', 'company_1', 'employee_1', expect.objectContaining(payload))
  })

  it('rejects pricing rules with malformed dates before service execution', async () => {
    const res = await request(app)
      .post('/api/v1/vehicles/vehicle_1/pricing/rules')
      .set('Authorization', 'Bearer employee-token')
      .send({
        name: 'Holiday',
        ruleType: 'HOLIDAY',
        startDate: 'July first-ish',
        endDate: '2026-07-10',
        dailyRate: 6000,
      })

    expect(res.status).toBe(400)
    expect(vehicleService.createVehiclePricingRule).not.toHaveBeenCalled()
  })

  it('requires manager access for pricing mutations', async () => {
    vi.mocked(prisma.employee.findUnique).mockResolvedValue(employee('AGENT') as never)

    const res = await request(app)
      .delete('/api/v1/vehicles/vehicle_1/pricing/rules/rule_1')
      .set('Authorization', 'Bearer employee-token')

    expect(res.status).toBe(403)
    expect(vehicleService.deleteVehiclePricingRule).not.toHaveBeenCalled()
  })
})
