import { Router } from 'express'
import { prisma } from '../lib/prisma'
import { requireCompanyAuth } from '../middleware/requireCompanyAuth'
import { requireTenant } from '../middleware/requireTenant'
import { requireSubscription } from '../middleware/requireSubscription'
import { generateFinancialReport, toCsv } from '../services/financialReportService'

const router = Router()
router.use(requireCompanyAuth, requireTenant, requireSubscription)

function getRangeFromPeriod(period: string) {
  const now = new Date()

  switch (period) {
    case 'WEEKLY': {
      const start = new Date(now)
      start.setDate(now.getDate() - 7)
      return { from: start, to: now }
    }
    case 'QUARTERLY': {
      const start = new Date(now.getFullYear(), now.getMonth() - 2, 1)
      return { from: start, to: now }
    }
    case 'ANNUAL': {
      const start = new Date(now.getFullYear(), 0, 1)
      return { from: start, to: now }
    }
    case 'MONTHLY':
    default:
      return { from: new Date(now.getFullYear(), now.getMonth(), 1), to: now }
  }
}

router.get('/summary', async (req, res, next) => {
  try {
    const { period = '30d' } = req.query as Record<string, 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: req.companyId, createdAt: { gte: since } } }),
      prisma.vehicle.count({ where: { companyId: req.companyId, status: 'AVAILABLE' } }),
      prisma.reservation.aggregate({ where: { companyId: req.companyId, status: { in: ['COMPLETED'] }, createdAt: { gte: since } }, _sum: { totalAmount: true } }),
      prisma.customer.count({ where: { companyId: req.companyId } }),
    ])

    res.json({ data: { totalReservations, activeVehicles, totalRevenue: totalRevenue._sum.totalAmount ?? 0, totalCustomers, period } })
  } catch (err) { next(err) }
})

router.get('/dashboard', async (req, res, next) => {
  try {
    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: req.companyId, createdAt: { gte: monthStart } } }),
      prisma.reservation.count({ where: { companyId: req.companyId, createdAt: { gte: prevMonthStart, lte: prevMonthEnd } } }),
      prisma.vehicle.count({ where: { companyId: req.companyId, status: { in: ['AVAILABLE', 'RENTED'] } } }),
      prisma.vehicle.count({ where: { companyId: req.companyId, createdAt: { lte: prevMonthEnd }, status: { in: ['AVAILABLE', 'RENTED'] } } }),
      prisma.customer.count({ where: { companyId: req.companyId } }),
      prisma.customer.count({ where: { companyId: req.companyId, createdAt: { lte: prevMonthEnd } } }),
      prisma.reservation.aggregate({ where: { companyId: req.companyId, status: { in: ['CONFIRMED', 'ACTIVE', 'COMPLETED'] }, createdAt: { gte: monthStart } }, _sum: { totalAmount: true } }),
      prisma.reservation.aggregate({ where: { companyId: req.companyId, status: { in: ['CONFIRMED', 'ACTIVE', 'COMPLETED'] }, createdAt: { gte: prevMonthStart, lte: prevMonthEnd } }, _sum: { totalAmount: true } }),
      prisma.reservation.findMany({
        where: { companyId: req.companyId },
        include: { customer: true, vehicle: true },
        orderBy: { createdAt: 'desc' },
        take: 8,
      }),
      prisma.reservation.groupBy({
        by: ['source'],
        where: { companyId: req.companyId },
        _count: { id: true },
        _sum: { totalAmount: true },
      }),
      prisma.subscription.findUnique({ where: { companyId: req.companyId } }),
    ])

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

    const typedRecentReservations = recentReservations as Array<{
      id: string
      contractNumber: string | null
      startDate: Date
      endDate: Date
      status: string
      totalAmount: number
      customer: { firstName: string; lastName: string }
      vehicle: { make: string; model: string }
    }>

    const typedSourceGroups = sourceGroups as Array<{
      source: string
      _count: { id: number }
      _sum: { totalAmount: number | null }
    }>

    res.json({
      data: {
        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: typedRecentReservations.map((reservation) => ({
          id: reservation.id,
          bookingRef: reservation.contractNumber ?? reservation.id.slice(-8).toUpperCase(),
          customerName: `${reservation.customer.firstName} ${reservation.customer.lastName}`,
          vehicleName: `${reservation.vehicle.make} ${reservation.vehicle.model}`,
          startDate: reservation.startDate,
          endDate: reservation.endDate,
          status: reservation.status,
          totalAmount: reservation.totalAmount,
        })),
        sourceBreakdown: typedSourceGroups.map((group) => ({
          source: group.source,
          count: group._count.id,
          revenue: group._sum.totalAmount ?? 0,
        })),
        subscription: subscription ? {
          status: subscription.status,
          planName: subscription.plan,
          trialEndsAt: subscription.trialEndAt,
        } : null,
      },
    })
  } catch (err) { next(err) }
})

router.get('/sources', async (req, res, next) => {
  try {
    const sources = await prisma.reservation.groupBy({ by: ['source'], where: { companyId: req.companyId }, _count: { id: true } })
    res.json({ data: sources })
  } catch (err) { next(err) }
})

router.get('/report', async (req, res, next) => {
  try {
    const { from, to, format = 'JSON', period } = req.query as Record<string, string>
    const accountingSettings = await prisma.accountingSettings.findUnique({ where: { companyId: req.companyId } })
    const derivedRange = getRangeFromPeriod(period || accountingSettings?.reportingPeriod || 'MONTHLY')
    const startDate = from ? new Date(from) : derivedRange.from
    const endDate = to ? new Date(to) : derivedRange.to

    const report = await generateFinancialReport(req.companyId, startDate, endDate)

    if (format === 'CSV') {
      res.setHeader('Content-Type', 'text/csv')
      res.setHeader('Content-Disposition', `attachment; filename="report-${startDate.toISOString().slice(0, 10)}-${endDate.toISOString().slice(0, 10)}.csv"`)
      return res.send(toCsv(report.rows))
    }

    res.json({ data: report })
  } catch (err) { next(err) }
})

export default router
