import { Router } from 'express'
import { z } from 'zod'
import { PLAN_PRICES } from '@rentaldrivego/types'
import { prisma } from '../lib/prisma'
import { requireCompanyAuth } from '../middleware/requireCompanyAuth'
import { requireTenant } from '../middleware/requireTenant'
import * as amanpay from '../services/amanpayService'
import * as paypal from '../services/paypalService'

const router = Router()

router.get('/plans', (_req, res) => {
  res.json({ data: PLAN_PRICES })
})

// ─── AmanPay subscription webhook (no auth) ──────────────────────────────────

router.post('/webhooks/amanpay', async (req, res, next) => {
  try {
    const rawBody = JSON.stringify(req.body)
    const signature = req.headers['x-amanpay-signature'] as string ?? ''

    if (amanpay.isConfigured() && !amanpay.verifyWebhookSignature(rawBody, signature)) {
      return res.status(401).json({ error: 'invalid_signature' })
    }

    const event = req.body
    const transactionId = event.transaction_id ?? event.id
    const status = event.status?.toUpperCase()

    if (status === 'PAID' || status === 'SUCCEEDED') {
      const invoice = await prisma.subscriptionInvoice.findFirst({
        where: { amanpayTransactionId: transactionId },
        include: { subscription: true },
      })
      if (invoice) {
        await prisma.subscriptionInvoice.update({
          where: { id: invoice.id },
          data: { status: 'PAID', paidAt: new Date() },
        })
        await prisma.subscription.update({
          where: { id: invoice.subscriptionId },
          data: {
            status: 'ACTIVE',
            currentPeriodStart: new Date(),
            currentPeriodEnd: addPeriod(new Date(), invoice.subscription.billingPeriod),
          },
        })
      }
    }

    res.json({ received: true })
  } catch (err) { next(err) }
})

// ─── PayPal subscription webhook (no auth) ───────────────────────────────────

router.post('/webhooks/paypal', async (req, res, next) => {
  try {
    const rawBody = JSON.stringify(req.body)
    const isValid = await paypal.verifyWebhookEvent(req.headers as Record<string, string>, rawBody)
    if (paypal.isConfigured() && !isValid) {
      return res.status(401).json({ error: 'invalid_signature' })
    }

    const event = req.body
    if (event.event_type === 'PAYMENT.CAPTURE.COMPLETED') {
      const captureId = event.resource?.id as string
      const invoice = await prisma.subscriptionInvoice.findFirst({
        where: { paypalCaptureId: captureId },
        include: { subscription: true },
      })
      if (invoice) {
        await prisma.subscriptionInvoice.update({
          where: { id: invoice.id },
          data: { status: 'PAID', paidAt: new Date() },
        })
        await prisma.subscription.update({
          where: { id: invoice.subscriptionId },
          data: {
            status: 'ACTIVE',
            currentPeriodStart: new Date(),
            currentPeriodEnd: addPeriod(new Date(), invoice.subscription.billingPeriod),
          },
        })
      }
    }

    res.json({ received: true })
  } catch (err) { next(err) }
})

// ─── PayPal capture redirect (no full auth needed — just valid session) ───────

router.post('/capture-paypal', requireCompanyAuth, requireTenant, async (req, res, next) => {
  try {
    const { paypalOrderId } = z.object({ paypalOrderId: z.string() }).parse(req.body)

    const invoice = await prisma.subscriptionInvoice.findFirstOrThrow({
      where: { paypalCaptureId: paypalOrderId, companyId: req.companyId },
      include: { subscription: true },
    })

    const capture = await paypal.captureOrder(paypalOrderId) as Record<string, any>
    const captureId = capture.purchase_units?.[0]?.payments?.captures?.[0]?.id ?? paypalOrderId

    await prisma.subscriptionInvoice.update({
      where: { id: invoice.id },
      data: { status: 'PAID', paidAt: new Date(), paypalCaptureId: captureId },
    })
    await prisma.subscription.update({
      where: { id: invoice.subscriptionId },
      data: {
        status: 'ACTIVE',
        currentPeriodStart: new Date(),
        currentPeriodEnd: addPeriod(new Date(), invoice.subscription.billingPeriod),
      },
    })

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

// ─── Authenticated subscription routes ───────────────────────────────────────

router.use(requireCompanyAuth, requireTenant)

router.get('/me', async (req, res, next) => {
  try {
    const subscription = await prisma.subscription.findUnique({
      where: { companyId: req.companyId },
      include: { invoices: { orderBy: { createdAt: 'desc' }, take: 12 } },
    })
    res.json({ data: subscription })
  } catch (err) { next(err) }
})

router.get('/invoices', async (req, res, next) => {
  try {
    const invoices = await prisma.subscriptionInvoice.findMany({
      where: { companyId: req.companyId },
      orderBy: { createdAt: 'desc' },
      take: 50,
    })
    res.json({ data: invoices })
  } catch (err) { next(err) }
})

const checkoutSchema = z.object({
  plan: z.enum(['STARTER', 'GROWTH', 'PRO']),
  billingPeriod: z.enum(['MONTHLY', 'ANNUAL']),
  currency: z.enum(['MAD', 'USD', 'EUR']),
  provider: z.enum(['AMANPAY', 'PAYPAL']),
  successUrl: z.string().url(),
  failureUrl: z.string().url(),
})

router.post('/checkout', async (req, res, next) => {
  try {
    const body = checkoutSchema.parse(req.body)
    const prices = PLAN_PRICES[body.plan]?.[body.billingPeriod]
    if (!prices) return res.status(400).json({ error: 'invalid_plan', message: 'Invalid plan or billing period', statusCode: 400 })
    const amount = prices[body.currency]
    if (!amount) return res.status(400).json({ error: 'invalid_currency', message: 'Currency not supported for this plan', statusCode: 400 })

    const company = await prisma.company.findUniqueOrThrow({ where: { id: req.companyId } })

    let subscription = await prisma.subscription.findUnique({ where: { companyId: req.companyId } })
    if (!subscription) {
      subscription = await prisma.subscription.create({
        data: {
          companyId: req.companyId,
          plan: body.plan,
          billingPeriod: body.billingPeriod,
          currency: body.currency,
          status: 'PENDING' as any,
        },
      })
    }

    const orderId = `sub-${req.companyId}-${Date.now()}`
    const description = `${body.plan} plan — ${body.billingPeriod}`
    const webhookBase = process.env.API_URL ?? 'http://localhost:4000'

    let checkoutUrl: string
    let amanpayTransactionId: string | null = null
    let paypalCaptureId: string | null = null

    if (body.provider === 'AMANPAY') {
      if (!amanpay.isConfigured()) {
        return res.status(503).json({ error: 'provider_not_configured', message: 'AmanPay is not configured on this platform', statusCode: 503 })
      }
      const result = await amanpay.createCheckout({
        amount,
        currency: body.currency,
        orderId,
        description,
        customerEmail: company.email,
        customerName: company.name,
        successUrl: body.successUrl,
        failureUrl: body.failureUrl,
        webhookUrl: `${webhookBase}/api/v1/subscriptions/webhooks/amanpay`,
      })
      checkoutUrl = result.checkoutUrl
      amanpayTransactionId = result.transactionId
    } else {
      if (!paypal.isConfigured()) {
        return res.status(503).json({ error: 'provider_not_configured', message: 'PayPal is not configured on this platform', statusCode: 503 })
      }
      const result = await paypal.createOrder({
        amount,
        currency: body.currency,
        orderId,
        description,
        returnUrl: body.successUrl,
        cancelUrl: body.failureUrl,
      })
      checkoutUrl = result.approveUrl
      paypalCaptureId = result.orderId
    }

    const invoice = await prisma.subscriptionInvoice.create({
      data: {
        companyId: req.companyId,
        subscriptionId: subscription.id,
        amount,
        currency: body.currency,
        status: 'PENDING',
        paymentProvider: body.provider,
        amanpayTransactionId,
        paypalCaptureId,
      },
    })

    res.json({ data: { invoice, checkoutUrl } })
  } catch (err) { next(err) }
})

router.post('/change-plan', async (req, res, next) => {
  try {
    const { plan, billingPeriod, currency } = z.object({
      plan: z.enum(['STARTER', 'GROWTH', 'PRO']),
      billingPeriod: z.enum(['MONTHLY', 'ANNUAL']),
      currency: z.enum(['MAD', 'USD', 'EUR']),
    }).parse(req.body)

    const updated = await prisma.subscription.update({
      where: { companyId: req.companyId },
      data: { plan, billingPeriod, currency },
    })

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

router.post('/cancel', async (req, res, next) => {
  try {
    const updated = await prisma.subscription.update({
      where: { companyId: req.companyId },
      data: { cancelAtPeriodEnd: true },
    })
    res.json({ data: updated })
  } catch (err) { next(err) }
})

router.post('/resume', async (req, res, next) => {
  try {
    const updated = await prisma.subscription.update({
      where: { companyId: req.companyId },
      data: { cancelAtPeriodEnd: false },
    })
    res.json({ data: updated })
  } catch (err) { next(err) }
})

// ─── Helpers ─────────────────────────────────────────────────────────────────

function addPeriod(date: Date, period: string): Date {
  const d = new Date(date)
  if (period === 'ANNUAL') {
    d.setFullYear(d.getFullYear() + 1)
  } else {
    d.setMonth(d.getMonth() + 1)
  }
  return d
}

export default router
