import { prisma } from '../../lib/prisma'

export async function findCompanyBySlug(slug: string) {
  return prisma.company.findFirstOrThrow({
    where: { slug, status: { in: ['ACTIVE', 'TRIALING', 'PAST_DUE', 'SUSPENDED'] } },
    include: { brand: true, contractSettings: true },
  })
}

export async function findPublishedVehicles(companyId: string) {
  return prisma.vehicle.findMany({
    where: { companyId, isPublished: true },
    orderBy: { createdAt: 'desc' },
  })
}

export async function findVehicleById(vehicleId: string, companyId: string) {
  return prisma.vehicle.findFirstOrThrow({
    where: { id: vehicleId, companyId, isPublished: true },
  })
}

export async function findActiveOffers(companyId: string) {
  return prisma.offer.findMany({
    where: { companyId, isActive: true, validFrom: { lte: new Date() }, validUntil: { gte: new Date() } },
    orderBy: [{ isFeatured: 'desc' }, { createdAt: 'desc' }],
  })
}

export async function findInsurancePolicies(companyId: string) {
  return prisma.insurancePolicy.findMany({
    where: { companyId, isActive: true },
    orderBy: [{ isRequired: 'desc' }, { sortOrder: 'asc' }, { name: 'asc' }],
  })
}

export async function findOfferByPromoCode(companyId: string, code: string) {
  return prisma.offer.findFirst({
    where: { companyId, promoCode: code, isActive: true, validFrom: { lte: new Date() }, validUntil: { gte: new Date() } },
  })
}

export async function upsertCustomer(companyId: string, data: {
  email: string
  firstName: string
  lastName: string
  phone: string
  driverLicense?: string
  dateOfBirth?: string
  licenseExpiry?: string
  licenseIssuedAt?: string
  nationality?: string
  identityDocumentNumber?: string
  fullAddress?: string
  licenseCountry?: string
  licenseNumber?: string | null
  licenseCategory?: string
  internationalLicenseNumber?: string | null
}) {
  const normalizedEmail = data.email.trim().toLowerCase()
  const existing = await prisma.customer.findUnique({
    where: { companyId_email: { companyId, email: normalizedEmail } },
    select: { id: true, address: true },
  })

  const addressPatch = {
    ...(data.fullAddress ? { fullAddress: data.fullAddress } : {}),
    ...(data.identityDocumentNumber ? { identityDocumentNumber: data.identityDocumentNumber } : {}),
    ...(data.internationalLicenseNumber !== undefined ? { internationalLicenseNumber: data.internationalLicenseNumber ?? null } : {}),
  }

  const address = Object.keys(addressPatch).length > 0
    ? {
        ...(existing?.address && typeof existing.address === 'object' && !Array.isArray(existing.address)
          ? existing.address as Record<string, unknown>
          : {}),
        ...addressPatch,
      }
    : undefined

  const payload = {
    firstName: data.firstName,
    lastName: data.lastName,
    email: normalizedEmail,
    phone: data.phone,
    ...(data.driverLicense ? { driverLicense: data.driverLicense } : {}),
    ...(data.dateOfBirth ? { dateOfBirth: new Date(data.dateOfBirth) } : {}),
    ...(data.nationality ? { nationality: data.nationality } : {}),
    ...(address ? { address } : {}),
    ...(data.licenseExpiry ? { licenseExpiry: new Date(data.licenseExpiry) } : {}),
    ...(data.licenseIssuedAt ? { licenseIssuedAt: new Date(data.licenseIssuedAt) } : {}),
    ...(data.licenseCountry ? { licenseCountry: data.licenseCountry } : {}),
    ...((data.licenseNumber ?? data.driverLicense) ? { licenseNumber: data.licenseNumber ?? data.driverLicense } : {}),
    ...(data.licenseCategory ? { licenseCategory: data.licenseCategory } : {}),
  }

  if (!existing) {
    return prisma.customer.create({
      data: { companyId, ...payload },
    })
  }

  return prisma.customer.update({
    where: { id: existing.id },
    data: payload,
  })
}

export async function createReservation(data: object) {
  return prisma.reservation.create({ data: data as any })
}

export async function findReservationWithDetails(reservationId: string) {
  return prisma.reservation.findUniqueOrThrow({
    where: { id: reservationId },
    include: { insurances: true, additionalDrivers: true, vehicle: true, customer: true, company: { include: { brand: true } } },
  })
}

export async function findBooking(reservationId: string, companyId: string) {
  return prisma.reservation.findFirstOrThrow({
    where: { id: reservationId, companyId },
    include: { vehicle: true, customer: true, company: { include: { brand: true } } },
  })
}

export async function findReservationForPayment(reservationId: string, companyId: string) {
  return prisma.reservation.findFirstOrThrow({
    where: { id: reservationId, companyId },
    include: { vehicle: true, customer: true, additionalDrivers: true },
  })
}

export async function createRentalPayment(data: {
  companyId: string; reservationId: string; amount: number; currency: string
  paymentProvider: string; amanpayTransactionId?: string | null; paypalCaptureId?: string | null
}) {
  return prisma.rentalPayment.create({
    data: { ...data, paymentProvider: data.paymentProvider as any, status: 'PENDING', type: 'CHARGE' },
  })
}

export async function findPaymentByPaypalOrderId(paypalOrderId: string, companyId: string) {
  return prisma.rentalPayment.findFirstOrThrow({ where: { paypalCaptureId: paypalOrderId, companyId } })
}

export async function capturePaypalPayment(paymentId: string, captureId: string, reservationId: string, amount: number) {
  await prisma.rentalPayment.update({ where: { id: paymentId }, data: { status: 'SUCCEEDED', paidAt: new Date(), paypalCaptureId: captureId } })
  await prisma.reservation.update({ where: { id: reservationId }, data: { paymentStatus: 'PAID', paidAmount: { increment: amount } } })
}


export async function createReservationPublicAccess(reservationId: string, tokenHash: string, expiresAt: Date) {
  return (prisma as any).reservationPublicAccess.create({
    data: { reservationId, tokenHash, expiresAt },
  })
}

export async function findReservationPublicAccess(reservationId: string, tokenHash: string) {
  return (prisma as any).reservationPublicAccess.findFirst({
    where: { reservationId, tokenHash, revokedAt: null, expiresAt: { gt: new Date() } },
  })
}

export async function markReservationPublicAccessUsed(id: string) {
  return (prisma as any).reservationPublicAccess.update({
    where: { id },
    data: { usedAt: new Date() },
  })
}
