import { prisma } from '../../lib/prisma'
import { generateFinancialReport, toCsv } from '../../services/financialReportService'

function getRangeFromPeriod(period: string) {
  const now = new Date()
  switch (period) {
    case 'WEEKLY':    return { from: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000), to: now }
    case 'QUARTERLY': return { from: new Date(now.getFullYear(), now.getMonth() - 2, 1), to: now }
    case 'ANNUAL':    return { from: new Date(now.getFullYear(), 0, 1), to: now }
    default:          return { from: new Date(now.getFullYear(), now.getMonth(), 1), to: now }
  }
}

function pct(current: number, previous: number) {
  if (previous === 0) return current > 0 ? 100 : 0
  return Math.round(((current - previous) / previous) * 100)
}

export async function getSummary(companyId: string, period: string) {
  const days  = parseInt(period.replace('d', '')) || 30
  const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000)
  const [totalReservations, activeVehicles, totalRevenue, totalCustomers] = await Promise.all([
    prisma.reservation.count({ where: { companyId, createdAt: { gte: since } } }),
    prisma.vehicle.count({ where: { companyId, status: 'AVAILABLE' } }),
    prisma.reservation.aggregate({ where: { companyId, status: { in: ['COMPLETED'] }, createdAt: { gte: since } }, _sum: { totalAmount: true } }),
    prisma.customer.count({ where: { companyId } }),
  ])
  return { totalReservations, activeVehicles, totalRevenue: totalRevenue._sum.totalAmount ?? 0, totalCustomers, period }
}

export async function getDashboard(companyId: string) {
  const now            = new Date()
  const monthStart     = new Date(now.getFullYear(), now.getMonth(), 1)
  const prevMonthStart = new Date(now.getFullYear(), now.getMonth() - 1, 1)
  const prevMonthEnd   = new Date(monthStart.getTime() - 1)

  const [
    totalBookings, previousBookings, activeVehicles, previousActiveVehicles,
    totalCustomers, previousCustomers, monthlyRevenueAgg, previousRevenueAgg,
    recentReservations, sourceGroups, subscription,
  ] = await Promise.all([
    prisma.reservation.count({ where: { companyId, createdAt: { gte: monthStart } } }),
    prisma.reservation.count({ where: { companyId, createdAt: { gte: prevMonthStart, lte: prevMonthEnd } } }),
    prisma.vehicle.count({ where: { companyId, status: { in: ['AVAILABLE', 'RENTED'] } } }),
    prisma.vehicle.count({ where: { companyId, createdAt: { lte: prevMonthEnd }, status: { in: ['AVAILABLE', 'RENTED'] } } }),
    prisma.customer.count({ where: { companyId } }),
    prisma.customer.count({ where: { companyId, createdAt: { lte: prevMonthEnd } } }),
    prisma.reservation.aggregate({ where: { companyId, status: { in: ['CONFIRMED', 'ACTIVE', 'COMPLETED'] }, createdAt: { gte: monthStart } }, _sum: { totalAmount: true } }),
    prisma.reservation.aggregate({ where: { companyId, status: { in: ['CONFIRMED', 'ACTIVE', 'COMPLETED'] }, createdAt: { gte: prevMonthStart, lte: prevMonthEnd } }, _sum: { totalAmount: true } }),
    prisma.reservation.findMany({ where: { companyId }, include: { customer: true, vehicle: true }, orderBy: { createdAt: 'desc' }, take: 8 }),
    prisma.reservation.groupBy({ by: ['source'], where: { companyId }, _count: { id: true }, _sum: { totalAmount: true } }),
    prisma.subscription.findUnique({ where: { companyId } }),
  ])

  return {
    kpis: {
      totalBookings,
      activeVehicles,
      monthlyRevenue:  monthlyRevenueAgg._sum.totalAmount ?? 0,
      totalCustomers,
      bookingsChange:  pct(totalBookings,   previousBookings),
      vehiclesChange:  pct(activeVehicles,  previousActiveVehicles),
      revenueChange:   pct(monthlyRevenueAgg._sum.totalAmount ?? 0, previousRevenueAgg._sum.totalAmount ?? 0),
      customersChange: pct(totalCustomers,  previousCustomers),
    },
    recentReservations: (recentReservations as any[]).map((r) => ({
      id:           r.id,
      bookingRef:   r.contractNumber ?? r.id.slice(-8).toUpperCase(),
      customerName: `${r.customer.firstName} ${r.customer.lastName}`,
      vehicleName:  `${r.vehicle.make} ${r.vehicle.model}`,
      startDate:    r.startDate,
      endDate:      r.endDate,
      status:       r.status,
      totalAmount:  r.totalAmount,
    })),
    sourceBreakdown: (sourceGroups as any[]).map((g) => ({
      source:  g.source,
      count:   g._count.id,
      revenue: g._sum.totalAmount ?? 0,
    })),
    subscription: subscription ? {
      status:      subscription.status,
      planName:    subscription.plan,
      trialEndsAt: subscription.trialEndAt,
    } : null,
  }
}

export async function getSources(companyId: string) {
  return prisma.reservation.groupBy({ by: ['source'], where: { companyId }, _count: { id: true } })
}

export async function getReport(companyId: string, query: { from?: string; to?: string; format: string; period?: string }) {
  const accountingSettings = await prisma.accountingSettings.findUnique({ where: { companyId } })
  const derivedRange = getRangeFromPeriod(query.period || accountingSettings?.reportingPeriod || 'MONTHLY')
  const startDate = query.from ? new Date(query.from) : derivedRange.from
  const endDate   = query.to   ? new Date(query.to)   : derivedRange.to
  const report    = await generateFinancialReport(companyId, startDate, endDate)
  return { report, startDate, endDate, format: query.format, csv: query.format === 'CSV' ? toCsv(report.rows) : null }
}
