import { Router } from 'express'
import { z } from 'zod'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import crypto from 'crypto'
import { authenticator } from 'otplib'
import qrcode from 'qrcode'
import { prisma } from '../lib/prisma'
import { requireAdminAuth, requireAdminRole } from '../middleware/requireAdminAuth'
import { getMarketplaceHomepageContent, saveMarketplaceHomepageContent } from '../services/platformContentService'
import { generateInvoicePdf, buildInvoiceNumber } from '../services/invoicePdfService'
import { sendTransactionalEmail } from '../services/notificationService'
import type { MarketplaceHomepageContent, MarketplaceHomepageMetric, MarketplaceHomepagePillar, MarketplaceHomepageSectionType, MarketplaceHomepageStep } from '@rentaldrivego/types'

const router = Router()

const permissionSchema = z.object({
  resource: z.enum(['COMPANIES', 'COMPANY_EMPLOYEES', 'SUBSCRIPTIONS', 'PAYMENTS', 'OFFERS', 'RENTERS', 'ADMIN_USERS', 'AUDIT_LOGS', 'PLATFORM_METRICS']),
  actions: z.array(z.enum(['READ', 'CREATE', 'UPDATE', 'DELETE', 'SUSPEND', 'IMPERSONATE'])).min(1),
})

const nullableString = z.union([z.string(), z.null()]).optional()
const nullableEmail = z.union([z.string().email(), z.null()]).optional()
const nullableUrl = z.union([z.string().url(), z.null()]).optional()
const nullableDate = z.union([
  z.string().datetime(),
  z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
  z.null(),
]).optional()

const homePageConfigSchema = z.object({
  heroTitle: nullableString,
  heroDescription: nullableString,
  viewOffersLabel: nullableString,
  viewPricingLabel: nullableString,
  contactCompanyLabel: nullableString,
  activeOffersTitle: nullableString,
  seeAllOffersLabel: nullableString,
  noActiveOffersLabel: nullableString,
  publishedVehiclesTitle: nullableString,
  viewVehicleLabel: nullableString,
  pricingEyebrow: nullableString,
  pricingTitle: nullableString,
  pricingDescription: nullableString,
  showOffers: z.boolean().optional(),
  showVehicles: z.boolean().optional(),
  showPricing: z.boolean().optional(),
  layout: z.object({
    items: z.array(z.object({
      id: z.string().min(1),
      type: z.enum(['hero', 'offers', 'vehicles', 'pricing']),
      x: z.number().int().min(1),
      y: z.number().int().min(1),
      w: z.number().int().min(1),
      h: z.number().int().min(1),
    })),
  }).optional(),
}).optional()

const menuConfigSchema = z.object({
  aboutLabel: nullableString,
  vehiclesLabel: nullableString,
  offersLabel: nullableString,
  pricingLabel: nullableString,
  blogLabel: nullableString,
  contactLabel: nullableString,
  bookCarLabel: nullableString,
  siteNavigationLabel: nullableString,
  showAbout: z.boolean().optional(),
  showVehicles: z.boolean().optional(),
  showOffers: z.boolean().optional(),
  showPricing: z.boolean().optional(),
  showBlog: z.boolean().optional(),
  showContact: z.boolean().optional(),
  pageSections: z.object({
    home: z.object({
      hero: z.boolean().optional(),
      offers: z.boolean().optional(),
      vehicles: z.boolean().optional(),
      pricing: z.boolean().optional(),
    }).optional(),
    about: z.object({
      hero: z.boolean().optional(),
      highlights: z.boolean().optional(),
      details: z.boolean().optional(),
    }).optional(),
    offers: z.object({
      header: z.boolean().optional(),
      grid: z.boolean().optional(),
    }).optional(),
    pricing: z.object({
      hero: z.boolean().optional(),
      plans: z.boolean().optional(),
      payments: z.boolean().optional(),
      faq: z.boolean().optional(),
    }).optional(),
    vehicles: z.object({
      header: z.boolean().optional(),
      filters: z.boolean().optional(),
      grid: z.boolean().optional(),
    }).optional(),
    vehicleDetail: z.object({
      gallery: z.boolean().optional(),
      summary: z.boolean().optional(),
    }).optional(),
    blog: z.object({
      hero: z.boolean().optional(),
      posts: z.boolean().optional(),
    }).optional(),
    contact: z.object({
      content: z.boolean().optional(),
    }).optional(),
    booking: z.object({
      content: z.boolean().optional(),
    }).optional(),
    bookingConfirmation: z.object({
      hero: z.boolean().optional(),
      summary: z.boolean().optional(),
      actions: z.boolean().optional(),
    }).optional(),
    }).optional(),
}).optional()

const marketplaceMetricSchema: z.ZodType<MarketplaceHomepageMetric> = z.object({
  value: z.string().min(1),
  label: z.string().min(1),
})

const marketplacePillarSchema: z.ZodType<MarketplaceHomepagePillar> = z.object({
  title: z.string().min(1),
  body: z.string().min(1),
})

const marketplaceStepSchema: z.ZodType<MarketplaceHomepageStep> = z.object({
  step: z.string().min(1),
  title: z.string().min(1),
  body: z.string().min(1),
})

const marketplaceSectionSchema: z.ZodType<MarketplaceHomepageSectionType> = z.enum([
  'hero',
  'surface',
  'pillars',
  'audiences',
  'features',
  'steps',
  'closing',
])

const marketplaceHomepageContentSchema: z.ZodType<MarketplaceHomepageContent> = z.object({
  sections: z.array(marketplaceSectionSchema).min(1),
  heroKicker: z.string().min(1),
  heroTitle: z.string().min(1),
  heroBody: z.string().min(1),
  startTrial: z.string().min(1),
  exploreVehicles: z.string().min(1),
  surfaceLabel: z.string().min(1),
  surfaceTitle: z.string().min(1),
  surfaceBody: z.string().min(1),
  liveLabel: z.string().min(1),
  trustedFleets: z.string().min(1),
  brandedFlows: z.string().min(1),
  multiTenant: z.string().min(1),
  companyKicker: z.string().min(1),
  companyTitle: z.string().min(1),
  companyBody: z.string().min(1),
  renterKicker: z.string().min(1),
  renterTitle: z.string().min(1),
  renterBody: z.string().min(1),
  pillars: z.array(marketplacePillarSchema).length(3),
  metrics: z.array(marketplaceMetricSchema).length(3),
  featureLabel: z.string().min(1),
  features: z.array(z.string().min(1)).min(1),
  stepsTitle: z.string().min(1),
  steps: z.array(marketplaceStepSchema).length(3),
  stepLabel: z.string().min(1),
  readyKicker: z.string().min(1),
  readyTitle: z.string().min(1),
  readyBody: z.string().min(1),
  viewPricing: z.string().min(1),
  createWorkspace: z.string().min(1),
})

const marketplaceHomepageConfigSchema = z.object({
  en: marketplaceHomepageContentSchema,
  fr: marketplaceHomepageContentSchema,
  ar: marketplaceHomepageContentSchema,
})

const adminCompanyUpdateSchema = z.object({
  company: z.object({
    name: z.string().min(1).optional(),
    slug: z.string().min(1).optional(),
    email: z.string().email().optional(),
    phone: nullableString,
    status: z.enum(['PENDING', 'TRIALING', 'ACTIVE', 'PAST_DUE', 'SUSPENDED', 'CANCELLED']).optional(),
    subscriptionPaymentRef: nullableString,
  }).optional(),
  subscription: z.object({
    plan: z.enum(['STARTER', 'GROWTH', 'PRO']).optional(),
    billingPeriod: z.enum(['MONTHLY', 'ANNUAL']).optional(),
    status: z.enum(['TRIALING', 'ACTIVE', 'PAST_DUE', 'CANCELLED', 'UNPAID']).optional(),
    currency: z.enum(['MAD', 'USD', 'EUR']).optional(),
    trialStartAt: nullableDate,
    trialEndAt: nullableDate,
    currentPeriodStart: nullableDate,
    currentPeriodEnd: nullableDate,
    cancelledAt: nullableDate,
    cancelAtPeriodEnd: z.boolean().optional(),
  }).optional(),
  brand: z.object({
    displayName: z.string().min(1).optional(),
    tagline: nullableString,
    subdomain: z.string().min(1).optional(),
    customDomain: nullableString,
    publicEmail: nullableEmail,
    publicPhone: nullableString,
    publicAddress: nullableString,
    publicCity: nullableString,
    publicCountry: nullableString,
    websiteUrl: nullableUrl,
    whatsappNumber: nullableString,
    defaultLocale: z.string().min(2).optional(),
    defaultCurrency: z.enum(['MAD', 'USD', 'EUR']).optional(),
    isListedOnMarketplace: z.boolean().optional(),
    homePageConfig: homePageConfigSchema,
    menuConfig: menuConfigSchema,
  }).optional(),
  contractSettings: z.object({
    legalName: nullableString,
    registrationNumber: nullableString,
    taxId: nullableString,
    terms: z.string().optional(),
    fuelPolicyType: z.enum(['FULL_TO_FULL', 'FULL_TO_EMPTY', 'SAME_TO_SAME', 'PREPAID', 'FREE']).optional(),
    lateFeePerHour: z.number().int().nullable().optional(),
    taxRate: z.number().nullable().optional(),
    signatureRequired: z.boolean().optional(),
    showTax: z.boolean().optional(),
  }).optional(),
  accountingSettings: z.object({
    reportingPeriod: z.enum(['WEEKLY', 'MONTHLY', 'QUARTERLY', 'ANNUAL']).optional(),
    fiscalYearStart: z.number().int().min(1).max(12).optional(),
    currency: z.enum(['MAD', 'USD', 'EUR']).optional(),
    accountantEmail: nullableEmail,
    accountantName: nullableString,
    autoSendReport: z.boolean().optional(),
    reportFormat: z.enum(['PDF', 'CSV', 'BOTH']).optional(),
  }).optional(),
})

function parseOptionalDate(value?: string | null) {
  if (!value) return null
  return new Date(value)
}

function toAuditJson<T>(value: T) {
  return JSON.parse(JSON.stringify(value))
}

function signAdminToken(adminId: string) {
  return jwt.sign({ sub: adminId, type: 'admin' }, process.env.JWT_SECRET!, { expiresIn: '8h' })
}

// ─── Auth ─────────────────────────────────────────────────────

router.post('/auth/login', async (req, res, next) => {
  try {
    const { email, password, totpCode } = z.object({ email: z.string().email().max(255).trim().toLowerCase(), password: z.string().max(128), totpCode: z.string().length(6).optional() }).parse(req.body)
    const admin = await prisma.adminUser.findUnique({ where: { email } })
    if (!admin || !admin.isActive) return res.status(401).json({ error: 'invalid_credentials', message: 'Invalid email or password', statusCode: 401 })

    const valid = await bcrypt.compare(password, admin.passwordHash)
    if (!valid) return res.status(401).json({ error: 'invalid_credentials', message: 'Invalid email or password', statusCode: 401 })

    if (admin.totpEnabled) {
      if (!totpCode) return res.status(401).json({ error: 'totp_required', message: '2FA code required', statusCode: 401 })
      const valid2fa = authenticator.verify({ token: totpCode, secret: admin.totpSecret! })
      if (!valid2fa) return res.status(401).json({ error: 'invalid_totp', message: 'Invalid 2FA code', statusCode: 401 })
    }

    await prisma.adminUser.update({ where: { id: admin.id }, data: { lastLoginAt: new Date(), lastLoginIp: req.ip } })
    const token = signAdminToken(admin.id)

    await prisma.auditLog.create({ data: { adminUserId: admin.id, action: 'ADMIN_LOGIN', resource: 'AdminUser', resourceId: admin.id, ipAddress: req.ip, userAgent: req.headers['user-agent'] } })

    res.json({ data: { token, admin: { id: admin.id, email: admin.email, firstName: admin.firstName, lastName: admin.lastName, role: admin.role, totpEnabled: admin.totpEnabled } } })
  } catch (err) { next(err) }
})

router.get('/auth/me', requireAdminAuth, (req, res) => {
  const { passwordHash, totpSecret, ...safe } = req.admin as any
  res.json({ data: safe })
})

router.post('/auth/2fa/setup', requireAdminAuth, async (req, res, next) => {
  try {
    const secret = authenticator.generateSecret()
    await prisma.adminUser.update({ where: { id: req.admin.id }, data: { totpSecret: secret } })
    const otpauth = authenticator.keyuri(req.admin.email, 'RentalDriveGo Admin', secret)
    const qr = await qrcode.toDataURL(otpauth)
    res.json({ data: { secret, qrCode: qr } })
  } catch (err) { next(err) }
})

router.post('/auth/2fa/verify', requireAdminAuth, async (req, res, next) => {
  try {
    const { code } = z.object({ code: z.string().length(6) }).parse(req.body)
    const admin = await prisma.adminUser.findUniqueOrThrow({ where: { id: req.admin.id } })
    if (!admin.totpSecret) return res.status(400).json({ error: 'no_totp_secret', message: '2FA setup not initiated', statusCode: 400 })
    const valid = authenticator.verify({ token: code, secret: admin.totpSecret })
    if (!valid) return res.status(400).json({ error: 'invalid_code', message: 'Invalid 2FA code', statusCode: 400 })
    await prisma.adminUser.update({ where: { id: admin.id }, data: { totpEnabled: true } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

const ADMIN_RESET_TOKEN_TTL_MINUTES = 60

router.post('/auth/forgot-password', async (req, res, next) => {
  try {
    const { email } = z.object({ email: z.string().email().max(255).trim().toLowerCase() }).parse(req.body)

    const admin = await prisma.adminUser.findUnique({ where: { email } })
    if (admin && admin.isActive) {
      const rawToken = crypto.randomBytes(32).toString('hex')
      const expiresAt = new Date(Date.now() + ADMIN_RESET_TOKEN_TTL_MINUTES * 60 * 1000)

      await prisma.adminUser.update({
        where: { id: admin.id },
        data: { passwordResetToken: rawToken, passwordResetExpiresAt: expiresAt },
      })

      const adminUrl = process.env.ADMIN_URL ?? 'http://localhost:3002'
      const resetUrl = `${adminUrl}/reset-password?token=${rawToken}`

      await sendTransactionalEmail({
        to: email,
        subject: 'Reset your RentalDriveGo admin password',
        html: `<p>Hi ${admin.firstName},</p><p>Reset your admin password here:</p><p><a href="${resetUrl}" style="background:#059669;color:#fff;padding:12px 24px;border-radius:8px;text-decoration:none;display:inline-block;font-weight:600;">Reset password</a></p><p>This link expires in ${ADMIN_RESET_TOKEN_TTL_MINUTES} minutes.</p><p>RentalDriveGo</p>`,
        text: `Hi ${admin.firstName},\n\nReset your admin password here: ${resetUrl}\n\nThis link expires in ${ADMIN_RESET_TOKEN_TTL_MINUTES} minutes.\n\nRentalDriveGo`,
      }).catch((err) => console.error('[AdminForgotPassword] Email send failed:', err?.message))
    }

    res.json({ data: { message: 'If that email is registered, a reset link has been sent.' } })
  } catch (err) { next(err) }
})

router.post('/auth/reset-password', async (req, res, next) => {
  try {
    const { token, password } = z.object({
      token: z.string().min(1),
      password: z.string().min(8).max(128),
    }).parse(req.body)

    const admin = await prisma.adminUser.findFirst({
      where: {
        passwordResetToken: token,
        passwordResetExpiresAt: { gt: new Date() },
      },
    })

    if (!admin) {
      return res.status(400).json({ error: 'invalid_token', message: 'Reset link is invalid or has expired.', statusCode: 400 })
    }

    const passwordHash = await bcrypt.hash(password, 12)

    await prisma.adminUser.update({
      where: { id: admin.id },
      data: {
        passwordHash,
        passwordResetToken: null,
        passwordResetExpiresAt: null,
      },
    })

    res.json({ data: { message: 'Password updated successfully. You can now sign in.' } })
  } catch (err) { next(err) }
})

// ─── Companies ────────────────────────────────────────────────

router.get('/companies', requireAdminAuth, async (req, res, next) => {
  try {
    const { q, status, plan, page = '1', pageSize = '20' } = req.query as Record<string, string>
    const where: any = {}
    if (status) where.status = status
    if (q) where.OR = [{ name: { contains: q, mode: 'insensitive' } }, { email: { contains: q, mode: 'insensitive' } }, { slug: { contains: q, mode: 'insensitive' } }]
    if (plan) where.subscription = { plan }

    const [companies, total] = await Promise.all([
      prisma.company.findMany({
        where,
        include: { brand: { select: { displayName: true, logoUrl: true, subdomain: true } }, subscription: { select: { plan: true, status: true } }, _count: { select: { employees: true, vehicles: true } } },
        skip: (parseInt(page) - 1) * parseInt(pageSize),
        take: parseInt(pageSize),
        orderBy: { createdAt: 'desc' },
      }),
      prisma.company.count({ where }),
    ])
    res.json({ data: companies, total, page: parseInt(page), pageSize: parseInt(pageSize), totalPages: Math.ceil(total / parseInt(pageSize)) })
  } catch (err) { next(err) }
})

router.get('/companies/:id', requireAdminAuth, async (req, res, next) => {
  try {
    const company = await prisma.company.findUniqueOrThrow({
      where: { id: req.params.id },
      include: {
        brand: true,
        contractSettings: true,
        accountingSettings: true,
        subscription: { include: { invoices: { orderBy: { createdAt: 'desc' }, take: 10 } } },
        employees: true,
        _count: { select: { employees: true, vehicles: true, customers: true, reservations: true } },
      },
    })
    res.json({ data: company })
  } catch (err) { next(err) }
})

router.get('/site-config/marketplace-homepage', requireAdminAuth, async (req, res, next) => {
  try {
    res.json({ data: await getMarketplaceHomepageContent() })
  } catch (err) { next(err) }
})

router.patch('/site-config/marketplace-homepage', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
  try {
    const { homepage } = z.object({ homepage: marketplaceHomepageConfigSchema }).parse(req.body)
    const saved = await saveMarketplaceHomepageContent(homepage)
    await prisma.auditLog.create({
      data: {
        adminUserId: req.admin.id,
        action: 'UPDATE',
        resource: 'MarketplaceHomepage',
        after: toAuditJson(saved),
        ipAddress: req.ip,
        userAgent: req.headers['user-agent'],
      },
    })
    res.json({ data: saved })
  } catch (err) { next(err) }
})

router.patch('/companies/:id', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
  try {
    const body = adminCompanyUpdateSchema.parse(req.body)
    const before = await prisma.company.findUniqueOrThrow({
      where: { id: req.params.id },
      include: {
        brand: true,
        contractSettings: true,
        accountingSettings: true,
        subscription: true,
      },
    })

    const updated = await prisma.$transaction(async (tx) => {
      if (body.company) {
        await tx.company.update({
          where: { id: req.params.id },
          data: body.company,
        })
      }

      if (body.subscription) {
        await tx.subscription.upsert({
          where: { companyId: req.params.id },
          update: {
            ...body.subscription,
            trialStartAt: parseOptionalDate(body.subscription.trialStartAt),
            trialEndAt: parseOptionalDate(body.subscription.trialEndAt),
            currentPeriodStart: parseOptionalDate(body.subscription.currentPeriodStart),
            currentPeriodEnd: parseOptionalDate(body.subscription.currentPeriodEnd),
            cancelledAt: parseOptionalDate(body.subscription.cancelledAt),
          },
          create: {
            companyId: req.params.id,
            plan: body.subscription.plan ?? 'STARTER',
            billingPeriod: body.subscription.billingPeriod ?? 'MONTHLY',
            status: body.subscription.status ?? 'TRIALING',
            currency: body.subscription.currency ?? 'MAD',
            trialStartAt: parseOptionalDate(body.subscription.trialStartAt),
            trialEndAt: parseOptionalDate(body.subscription.trialEndAt),
            currentPeriodStart: parseOptionalDate(body.subscription.currentPeriodStart),
            currentPeriodEnd: parseOptionalDate(body.subscription.currentPeriodEnd),
            cancelledAt: parseOptionalDate(body.subscription.cancelledAt),
            cancelAtPeriodEnd: body.subscription.cancelAtPeriodEnd ?? false,
          } as any,
        })
      }

      if (body.brand) {
        const currentCompany = await tx.company.findUniqueOrThrow({ where: { id: req.params.id } })
        await tx.brandSettings.upsert({
          where: { companyId: req.params.id },
          update: body.brand,
          create: {
            companyId: req.params.id,
            displayName: body.brand.displayName ?? currentCompany.name,
            subdomain: body.brand.subdomain ?? currentCompany.slug,
            paymentMethodsEnabled: before.brand?.paymentMethodsEnabled ?? [],
            ...body.brand,
          } as any,
        })
      }

      if (body.contractSettings) {
        await tx.contractSettings.upsert({
          where: { companyId: req.params.id },
          update: body.contractSettings,
          create: {
            companyId: req.params.id,
            ...body.contractSettings,
          } as any,
        })
      }

      if (body.accountingSettings) {
        await tx.accountingSettings.upsert({
          where: { companyId: req.params.id },
          update: body.accountingSettings,
          create: {
            companyId: req.params.id,
            ...body.accountingSettings,
          } as any,
        })
      }

      return tx.company.findUniqueOrThrow({
        where: { id: req.params.id },
        include: {
          brand: true,
          contractSettings: true,
          accountingSettings: true,
          subscription: { include: { invoices: { orderBy: { createdAt: 'desc' }, take: 10 } } },
          employees: true,
          _count: { select: { employees: true, vehicles: true, customers: true, reservations: true } },
        },
      })
    })

    await prisma.auditLog.create({
      data: {
        adminUserId: req.admin.id,
        action: 'UPDATE_COMPANY',
        resource: 'Company',
        resourceId: req.params.id,
        companyId: req.params.id,
        before: toAuditJson(before),
        after: toAuditJson(body),
        ipAddress: req.ip,
      },
    })

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

router.patch('/companies/:id/status', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
  try {
    const { status, reason } = z.object({ status: z.enum(['ACTIVE','SUSPENDED','CANCELLED']), reason: z.string().optional() }).parse(req.body)
    const before = await prisma.company.findUniqueOrThrow({ where: { id: req.params.id } })
    const updated = await prisma.company.update({ where: { id: req.params.id }, data: { status } })
    await prisma.auditLog.create({ data: { adminUserId: req.admin.id, action: `SET_COMPANY_STATUS_${status}`, resource: 'Company', resourceId: req.params.id, companyId: req.params.id, before: { status: before.status }, after: { status }, note: reason, ipAddress: req.ip } })
    res.json({ data: updated })
  } catch (err) { next(err) }
})

router.delete('/companies/:id', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
  try {
    await prisma.company.delete({ where: { id: req.params.id } })
    await prisma.auditLog.create({ data: { adminUserId: req.admin.id, action: 'DELETE_COMPANY', resource: 'Company', resourceId: req.params.id, ipAddress: req.ip } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

// ─── Impersonation ────────────────────────────────────────────

router.post('/companies/:id/impersonate', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
  try {
    const company = await prisma.company.findUniqueOrThrow({ where: { id: req.params.id }, include: { employees: { where: { role: 'OWNER' } } } })
    const token = jwt.sign({ companyId: company.id, employeeId: company.employees[0]?.id, isImpersonation: true }, process.env.JWT_SECRET!, { expiresIn: '30m' })
    await prisma.auditLog.create({ data: { adminUserId: req.admin.id, action: 'IMPERSONATE_COMPANY', resource: 'Company', resourceId: company.id, companyId: company.id, ipAddress: req.ip } })
    res.json({ data: { token, expiresIn: 1800 } })
  } catch (err) { next(err) }
})

// ─── Renters ──────────────────────────────────────────────────

router.get('/renters', requireAdminAuth, async (req, res, next) => {
  try {
    const { q, blocked, page = '1', pageSize = '20' } = req.query as Record<string, string>
    const where: any = {}
    if (blocked !== undefined) where.isActive = blocked === 'false'
    if (q) where.OR = [{ firstName: { contains: q, mode: 'insensitive' } }, { email: { contains: q, mode: 'insensitive' } }]
    const [renters, total] = await Promise.all([
      prisma.renter.findMany({ where, select: { id: true, firstName: true, lastName: true, email: true, phone: true, isActive: true, createdAt: true, _count: { select: { reservations: true } } }, skip: (parseInt(page) - 1) * parseInt(pageSize), take: parseInt(pageSize), orderBy: { createdAt: 'desc' } }),
      prisma.renter.count({ where }),
    ])
    res.json({ data: renters, total, page: parseInt(page), pageSize: parseInt(pageSize), totalPages: Math.ceil(total / parseInt(pageSize)) })
  } catch (err) { next(err) }
})

router.post('/renters/:id/block', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
  try {
    await prisma.renter.update({ where: { id: req.params.id }, data: { isActive: false } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

router.post('/renters/:id/unblock', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
  try {
    await prisma.renter.update({ where: { id: req.params.id }, data: { isActive: true } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

// ─── Metrics ──────────────────────────────────────────────────

router.get('/metrics', requireAdminAuth, requireAdminRole('FINANCE'), async (req, res, next) => {
  try {
    const [totalCompanies, activeCompanies, trialingCompanies, suspendedCompanies, totalRenters, totalReservations] = await Promise.all([
      prisma.company.count(),
      prisma.company.count({ where: { status: 'ACTIVE' } }),
      prisma.company.count({ where: { status: 'TRIALING' } }),
      prisma.company.count({ where: { status: 'SUSPENDED' } }),
      prisma.renter.count(),
      prisma.reservation.count(),
    ])
    res.json({ data: { totalCompanies, activeCompanies, trialingCompanies, suspendedCompanies, totalRenters, totalReservations } })
  } catch (err) { next(err) }
})

// ─── Audit Log ────────────────────────────────────────────────

router.get('/audit-logs', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
  try {
    const { adminId, action, companyId, entityId, page = '1', pageSize = '50' } = req.query as Record<string, string>
    const where: any = {}
    if (adminId)   where.adminUserId = adminId
    if (action)    where.action = { contains: action }
    if (companyId) where.companyId = companyId
    if (entityId) where.resourceId = entityId
    const [logs, total] = await Promise.all([
      prisma.auditLog.findMany({ where, include: { adminUser: { select: { firstName: true, lastName: true, email: true } } }, skip: (parseInt(page) - 1) * parseInt(pageSize), take: parseInt(pageSize), orderBy: { createdAt: 'desc' } }),
      prisma.auditLog.count({ where }),
    ])
    res.json({ data: logs, total, page: parseInt(page), pageSize: parseInt(pageSize), totalPages: Math.ceil(total / parseInt(pageSize)) })
  } catch (err) { next(err) }
})

// ─── Admin Users (SUPER_ADMIN only) ───────────────────────────

router.get('/admins', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async (req, res, next) => {
  try {
    const admins = await prisma.adminUser.findMany({
      select: {
        id: true,
        email: true,
        firstName: true,
        lastName: true,
        role: true,
        isActive: true,
        totpEnabled: true,
        lastLoginAt: true,
        createdAt: true,
        permissions: true,
      },
    })
    res.json({ data: admins })
  } catch (err) { next(err) }
})

router.post('/admins', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async (req, res, next) => {
  try {
    const body = z.object({
      email: z.string().email(),
      firstName: z.string(),
      lastName: z.string(),
      role: z.enum(['SUPER_ADMIN', 'ADMIN', 'SUPPORT', 'FINANCE', 'VIEWER']),
      password: z.string().min(8),
      permissions: z.array(permissionSchema).optional(),
    }).parse(req.body)
    const passwordHash = await bcrypt.hash(body.password, 12)
    const admin = await prisma.adminUser.create({
      data: {
        email: body.email,
        firstName: body.firstName,
        lastName: body.lastName,
        role: body.role,
        passwordHash,
        permissions: body.permissions ? {
          create: body.permissions,
        } : undefined,
      },
      include: { permissions: true },
    })
    const { passwordHash: _, ...safe } = admin
    res.status(201).json({ data: safe })
  } catch (err) { next(err) }
})

router.patch('/admins/:id/role', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async (req, res, next) => {
  try {
    const { role } = z.object({ role: z.enum(['SUPER_ADMIN', 'ADMIN','SUPPORT','FINANCE','VIEWER']) }).parse(req.body)
    await prisma.adminUser.update({ where: { id: req.params.id }, data: { role } })
    res.json({ data: { success: true } })
  } catch (err) { next(err) }
})

router.patch('/admins/:id/permissions', requireAdminAuth, requireAdminRole('SUPER_ADMIN'), async (req, res, next) => {
  try {
    const { permissions } = z.object({ permissions: z.array(permissionSchema) }).parse(req.body)
    await prisma.adminUser.findUniqueOrThrow({ where: { id: req.params.id } })
    await prisma.$transaction([
      prisma.adminPermission.deleteMany({ where: { adminUserId: req.params.id } }),
      prisma.adminPermission.createMany({
        data: permissions.map((permission) => ({
          adminUserId: req.params.id,
          resource: permission.resource,
          actions: permission.actions,
        })) as any,
      }),
    ])
    const admin = await prisma.adminUser.findUniqueOrThrow({
      where: { id: req.params.id },
      include: { permissions: true },
    })
    res.json({ data: admin })
  } catch (err) { next(err) }
})

// ─── Billing ──────────────────────────────────────────────────

const PLAN_MONTHLY_AMOUNT: Record<string, number> = {
  STARTER: 29900,
  GROWTH: 59900,
  PRO: 99900,
}

router.get('/billing', requireAdminAuth, requireAdminRole('FINANCE'), async (req, res, next) => {
  try {
    const { status, plan, page = '1', pageSize = '20' } = req.query as Record<string, string>
    const where: any = {}
    if (status) where.status = status
    if (plan) where.plan = plan

    const [subscriptions, total] = await Promise.all([
      prisma.subscription.findMany({
        where,
        include: {
          company: { select: { id: true, name: true, email: true, slug: true, status: true } },
          invoices: { select: { id: true, amount: true, currency: true, status: true, paidAt: true, createdAt: true }, orderBy: { createdAt: 'desc' }, take: 5 },
          _count: { select: { invoices: true } },
        },
        skip: (parseInt(page) - 1) * parseInt(pageSize),
        take: parseInt(pageSize),
        orderBy: { createdAt: 'desc' },
      }),
      prisma.subscription.count({ where }),
    ])

    const activeStatuses = ['ACTIVE', 'TRIALING'] as any[]
    const allActive = await prisma.subscription.findMany({
      where: { status: { in: activeStatuses } },
      select: { plan: true, billingPeriod: true, currency: true },
    })

    let mrr = 0
    for (const sub of allActive) {
      const monthly = PLAN_MONTHLY_AMOUNT[sub.plan] ?? 0
      mrr += sub.billingPeriod === 'ANNUAL' ? Math.round(monthly * 10 / 12) : monthly
    }

    const [activeCount, trialingCount, pastDueCount, cancelledCount] = await Promise.all([
      prisma.subscription.count({ where: { status: 'ACTIVE' } }),
      prisma.subscription.count({ where: { status: 'TRIALING' } }),
      prisma.subscription.count({ where: { status: 'PAST_DUE' } }),
      prisma.subscription.count({ where: { status: 'CANCELLED' } }),
    ])

    res.json({
      data: subscriptions,
      total,
      page: parseInt(page),
      pageSize: parseInt(pageSize),
      totalPages: Math.ceil(total / parseInt(pageSize)),
      stats: { mrr, activeCount, trialingCount, pastDueCount, cancelledCount },
    })
  } catch (err) { next(err) }
})

router.get('/billing/:companyId/invoices', requireAdminAuth, requireAdminRole('FINANCE'), async (req, res, next) => {
  try {
    const { page = '1', pageSize = '20' } = req.query as Record<string, string>
    const [invoices, total] = await Promise.all([
      prisma.subscriptionInvoice.findMany({
        where: { companyId: req.params.companyId },
        orderBy: { createdAt: 'desc' },
        skip: (parseInt(page) - 1) * parseInt(pageSize),
        take: parseInt(pageSize),
      }),
      prisma.subscriptionInvoice.count({ where: { companyId: req.params.companyId } }),
    ])
    res.json({ data: invoices, total, page: parseInt(page), pageSize: parseInt(pageSize), totalPages: Math.ceil(total / parseInt(pageSize)) })
  } catch (err) { next(err) }
})

router.get('/billing/invoices/:invoiceId/pdf', requireAdminAuth, requireAdminRole('FINANCE'), async (req, res, next) => {
  try {
    const invoice = await prisma.subscriptionInvoice.findUniqueOrThrow({
      where: { id: req.params.invoiceId },
      include: {
        company: { select: { name: true, email: true, phone: true, address: true } },
        subscription: { select: { plan: true, billingPeriod: true, currency: true, currentPeriodStart: true, currentPeriodEnd: true } },
      },
    })

    const invoiceNumber = buildInvoiceNumber(invoice.id, invoice.createdAt)
    const transactionId = invoice.amanpayTransactionId ?? invoice.paypalCaptureId ?? null

    const pdfBuffer = await generateInvoicePdf({
      invoiceNumber,
      issueDate: invoice.createdAt.toISOString(),
      dueDate: invoice.status === 'PENDING' ? invoice.createdAt.toISOString() : null,
      company: {
        name: invoice.company.name,
        email: invoice.company.email,
        phone: invoice.company.phone,
        address: invoice.company.address,
      },
      subscription: {
        plan: invoice.subscription.plan,
        billingPeriod: invoice.subscription.billingPeriod,
        currentPeriodStart: invoice.subscription.currentPeriodStart?.toISOString(),
        currentPeriodEnd: invoice.subscription.currentPeriodEnd?.toISOString(),
        currency: invoice.subscription.currency,
      },
      amount: invoice.amount,
      currency: invoice.currency,
      status: invoice.status,
      paymentProvider: invoice.paymentProvider,
      transactionId,
      paidAt: invoice.paidAt?.toISOString(),
    })

    res.setHeader('Content-Type', 'application/pdf')
    res.setHeader('Content-Disposition', `attachment; filename="${invoiceNumber}.pdf"`)
    res.setHeader('Content-Length', pdfBuffer.length)
    res.end(pdfBuffer)
  } catch (err) { next(err) }
})

export default router
