import { prisma } from '../../lib/prisma'
import { AppError } from '../../http/errors'
import { buildReservationWorkflow } from './reservation.presenter'
import * as repo from './reservation.repo'

export async function getInspections(reservationId: string, companyId: string) {
  return repo.findInspections(reservationId, companyId)
}

export async function upsertInspection(
  reservationId: string,
  companyId: string,
  type: 'CHECKIN' | 'CHECKOUT',
  body: {
    mileage?: number
    fuelLevel: string
    fuelCharge?: number
    generalCondition?: string
    employeeNotes?: string
    customerAgreed?: boolean
    damagePoints?: Array<{
      viewType: string; x: number; y: number; damageType: string
      severity?: string; description?: string; isPreExisting?: boolean
    }>
  },
  inspectedBy: string,
) {
  const reservation = await repo.findForInspection(reservationId, companyId)
  const workflow    = buildReservationWorkflow(reservation)

  if (workflow.closed) throw new AppError('This reservation has already been closed', 400, 'reservation_closed')
  if (type === 'CHECKIN' && !workflow.checkInInspectionEditable) {
    throw new AppError('Check-in inspection is not editable at this stage', 400, 'invalid_status')
  }
  if (type === 'CHECKOUT' && !workflow.checkOutInspectionEditable) {
    throw new AppError('Check-out inspection is only editable after the vehicle is returned', 400, 'invalid_status')
  }

  const inspection = await prisma.damageInspection.upsert({
    where: { reservationId_type: { reservationId, type } },
    update: {
      mileage: body.mileage ?? null,
      fuelLevel: body.fuelLevel as any,
      fuelCharge: body.fuelCharge ?? null,
      generalCondition: body.generalCondition ?? null,
      employeeNotes: body.employeeNotes ?? null,
      customerAgreed: body.customerAgreed ?? false,
      inspectedBy,
      inspectedAt: new Date(),
      damagePoints: { deleteMany: {}, create: body.damagePoints as any },
    },
    create: {
      reservationId, companyId, type,
      mileage: body.mileage ?? null,
      fuelLevel: body.fuelLevel as any,
      fuelCharge: body.fuelCharge ?? null,
      generalCondition: body.generalCondition ?? null,
      employeeNotes: body.employeeNotes ?? null,
      customerAgreed: body.customerAgreed ?? false,
      inspectedBy,
      damagePoints: { create: body.damagePoints as any },
    },
    include: { damagePoints: true },
  })

  const damageData = (body.damagePoints ?? []).map((p) => ({
    viewType: p.viewType, x: p.x, y: p.y, damageType: p.damageType,
    severity: p.severity ?? 'MINOR', note: p.description ?? '', isPreExisting: p.isPreExisting ?? false,
  }))

  await prisma.damageReport.upsert({
    where: { reservationId_type: { reservationId, type } },
    update: {
      damages: damageData,
      fuelLevel: body.fuelLevel as any,
      mileage: body.mileage ?? null,
      inspectedAt: new Date(),
      inspectedBy,
      customerSignedAt: (body.customerAgreed ?? false) ? new Date() : null,
      customerName: `${reservation.customer.firstName} ${reservation.customer.lastName}`,
    },
    create: {
      reservationId, companyId, type,
      damages: damageData,
      photos: [],
      fuelLevel: body.fuelLevel as any,
      mileage: body.mileage ?? null,
      inspectedAt: new Date(),
      inspectedBy,
      customerSignedAt: (body.customerAgreed ?? false) ? new Date() : null,
      customerName: `${reservation.customer.firstName} ${reservation.customer.lastName}`,
    },
  })

  await prisma.reservation.update({
    where: { id: reservationId },
    data: type === 'CHECKIN'
      ? { checkInMileage: body.mileage ?? null, checkInFuelLevel: body.fuelLevel }
      : { checkOutMileage: body.mileage ?? null, checkOutFuelLevel: body.fuelLevel },
  })

  return inspection
}
