import { Router } from 'express'
import { z } from 'zod'
import { prisma } from '../lib/prisma'
import { requireCompanyAuth } from '../middleware/requireCompanyAuth'
import { requireTenant } from '../middleware/requireTenant'
import { requireSubscription } from '../middleware/requireSubscription'
import { requireRole } from '../middleware/requireRole'
import { validateAndFlagLicense } from '../services/licenseValidationService'

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

const paginationSchema = z.object({
  page:     z.coerce.number().int().min(1).max(10000).default(1),
  pageSize: z.coerce.number().int().min(1).max(100).default(20),
})

const customerSchema = z.object({
  firstName:       z.string().min(1).max(100).trim(),
  lastName:        z.string().min(1).max(100).trim(),
  email:           z.string().email().max(255).trim().toLowerCase(),
  phone:           z.string().max(30).trim().optional(),
  driverLicense:   z.string().max(50).trim().optional(),
  dateOfBirth:     z.string().datetime().optional(),
  nationality:     z.string().max(100).trim().optional(),
  address:         z.record(z.unknown()).optional(),
  notes:           z.string().max(2000).trim().optional(),
  licenseExpiry:   z.string().datetime().optional(),
  licenseIssuedAt: z.string().datetime().optional(),
  licenseCountry:  z.string().max(100).trim().optional(),
  licenseNumber:   z.string().max(50).trim().optional(),
  licenseCategory: z.string().max(20).trim().optional(),
})

router.get('/', async (req, res, next) => {
  try {
    const { q, flagged } = req.query as Record<string, string>
    const { page, pageSize } = paginationSchema.parse(req.query)
    const safeQ = q ? q.trim().slice(0, 100) : undefined
    const where: any = { companyId: req.companyId }
    if (flagged !== undefined) where.flagged = flagged === 'true'
    if (safeQ) where.OR = [{ firstName: { contains: safeQ, mode: 'insensitive' } }, { lastName: { contains: safeQ, mode: 'insensitive' } }, { email: { contains: safeQ, mode: 'insensitive' } }]

    const [customers, total] = await Promise.all([
      prisma.customer.findMany({ where, skip: (page - 1) * pageSize, take: pageSize, orderBy: { createdAt: 'desc' } }),
      prisma.customer.count({ where }),
    ])
    res.json({ data: customers, total, page, pageSize, totalPages: Math.ceil(total / pageSize) })
  } catch (err) { next(err) }
})

router.post('/', async (req, res, next) => {
  try {
    const body = customerSchema.parse(req.body)
    const customer = await prisma.customer.create({
      data: {
        ...body,
        companyId: req.companyId,
        dateOfBirth:     body.dateOfBirth     ? new Date(body.dateOfBirth)     : null,
        licenseExpiry:   body.licenseExpiry   ? new Date(body.licenseExpiry)   : null,
        licenseIssuedAt: body.licenseIssuedAt ? new Date(body.licenseIssuedAt) : null,
      } as any,
    })
    if (body.licenseExpiry) {
      await validateAndFlagLicense(customer.id).catch(() => null)
    }
    res.status(201).json({ data: customer })
  } catch (err) { next(err) }
})

router.get('/:id', async (req, res, next) => {
  try {
    const customer = await prisma.customer.findFirstOrThrow({
      where: { id: req.params.id, companyId: req.companyId },
      include: { reservations: { include: { vehicle: true }, orderBy: { createdAt: 'desc' }, take: 20 } },
    })
    res.json({ data: customer })
  } catch (err) { next(err) }
})

router.patch('/:id', async (req, res, next) => {
  try {
    const body = customerSchema.partial().parse(req.body)
    const updated = await prisma.customer.updateMany({ where: { id: req.params.id, companyId: req.companyId }, data: { ...body, dateOfBirth: body.dateOfBirth ? new Date(body.dateOfBirth) : undefined, licenseExpiry: body.licenseExpiry ? new Date(body.licenseExpiry) : undefined, licenseIssuedAt: body.licenseIssuedAt ? new Date(body.licenseIssuedAt) : undefined } as any })
    if (updated.count === 0) return res.status(404).json({ error: 'not_found', message: 'Customer not found', statusCode: 404 })
    if (body.licenseExpiry) await validateAndFlagLicense(req.params.id).catch(() => null)
    const customer = await prisma.customer.findUniqueOrThrow({ where: { id: req.params.id } })
    res.json({ data: customer })
  } catch (err) { next(err) }
})

router.post('/:id/flag', async (req, res, next) => {
  try {
    const { reason } = z.object({ reason: z.string().optional() }).parse(req.body)
    await prisma.customer.updateMany({ where: { id: req.params.id, companyId: req.companyId }, data: { flagged: true, flagReason: reason ?? null } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

router.delete('/:id/flag', async (req, res, next) => {
  try {
    await prisma.customer.updateMany({ where: { id: req.params.id, companyId: req.companyId }, data: { flagged: false, flagReason: null } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

router.post('/:id/validate-license', async (req, res, next) => {
  try {
    const customer = await prisma.customer.findFirstOrThrow({ where: { id: req.params.id, companyId: req.companyId } })
    const result = await validateAndFlagLicense(customer.id)
    res.json({ data: result })
  } catch (err) { next(err) }
})

router.post('/:id/approve-license', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { decision, note } = z.object({ decision: z.enum(['APPROVE', 'DENY']), note: z.string().optional() }).parse(req.body)
    const customer = await prisma.customer.findFirstOrThrow({ where: { id: req.params.id, companyId: req.companyId } })
    const updated = await prisma.customer.update({
      where: { id: customer.id },
      data: {
        licenseValidationStatus: decision === 'APPROVE' ? 'APPROVED' : 'DENIED',
        licenseApprovedBy:  `${req.employee.firstName} ${req.employee.lastName}`,
        licenseApprovedAt:  new Date(),
        licenseApprovalNote: note ?? null,
      },
    })
    res.json({ data: updated })
  } catch (err) { next(err) }
})

export default router
