import { NextResponse } from 'next/server';
import { withErrorHandler } from '@server/middleware/withErrorHandler';
import { withAuth, AuthedRequest } from '@server/middleware/withAuth';
import { ValidationError } from '@server/errors';
import { getRazorpayClient, getRazorpayCredentials } from '@server/lib/razorpay';
import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';
import { initDatabase } from '@server/db/init';
import { createHmac } from 'crypto';
import { childLogger } from '@server/logger';

const log = childLogger('route.billing.razorpay-verify');

export const POST = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    await initDatabase();
    let _body: Awaited<ReturnType<typeof req.json>>;
    try {
      _body = await req.json();
    } catch {
      throw new ValidationError('Request body must be valid JSON');
    }
    const { razorpaySubscriptionId, razorpayPaymentId, razorpaySignature } = _body;

    if (!razorpaySubscriptionId || !razorpayPaymentId || !razorpaySignature) {
      return NextResponse.json({ error: 'Missing payment verification fields', code: 'VALIDATION_ERROR' }, { status: 400 });
    }

    const creds = await getRazorpayCredentials();
    if (!creds) {
      return NextResponse.json({ error: 'Razorpay not configured', code: 'GATEWAY_NOT_CONFIGURED' }, { status: 503 });
    }

    const expectedSig = createHmac('sha256', creds.keySecret)
      .update(`${razorpayPaymentId}|${razorpaySubscriptionId}`)
      .digest('hex');

    if (expectedSig !== razorpaySignature) {
      log.warn({ razorpaySubscriptionId }, 'Razorpay signature verification failed');
      return NextResponse.json({ error: 'Payment signature verification failed', code: 'SIGNATURE_INVALID' }, { status: 400 });
    }

    const razorpay = await getRazorpayClient();
    if (!razorpay) {
      return NextResponse.json({ error: 'Razorpay not available', code: 'GATEWAY_NOT_CONFIGURED' }, { status: 503 });
    }

    let planId: string | null = null;
    let billingCycle: string = 'monthly';
    let subCurrency = 'INR';
    let subRestaurantId: string | null = null;

    try {
      const rzpSub = await (razorpay.subscriptions.fetch as (id: string) => Promise<{
        id: string; plan_id: string; status: string;
        notes?: { plan_id?: string; billing_cycle?: string; restaurant_id?: string; currency?: string };
      }>)(razorpaySubscriptionId);
      planId = rzpSub.notes?.plan_id ?? null;
      billingCycle = rzpSub.notes?.billing_cycle ?? 'monthly';
      subCurrency = rzpSub.notes?.currency ?? 'INR';
      subRestaurantId = rzpSub.notes?.restaurant_id ?? null;
    } catch (err) {
      log.error({ err, razorpaySubscriptionId }, 'Failed to fetch Razorpay subscription for verification');
      return NextResponse.json({ error: 'Failed to validate subscription details', code: 'GATEWAY_ERROR' }, { status: 502 });
    }

    const restaurantId = req.session.restaurantId!;

    if (subRestaurantId && subRestaurantId !== restaurantId) {
      log.warn({ subRestaurantId, restaurantId }, 'Razorpay subscription restaurant mismatch');
      return NextResponse.json({ error: 'Subscription does not belong to this account', code: 'FORBIDDEN' }, { status: 403 });
    }

    if (!planId) {
      return NextResponse.json({ error: 'Subscription is missing plan information', code: 'VALIDATION_ERROR' }, { status: 400 });
    }

    try {
      await db.execute(sql`
        INSERT INTO public.subscriptions (restaurant_id, plan_id, status, razorpay_subscription_id)
        VALUES (${restaurantId}, ${planId}, 'active', ${razorpaySubscriptionId})
        ON CONFLICT (restaurant_id) DO UPDATE SET
          plan_id = EXCLUDED.plan_id,
          status = 'active',
          razorpay_subscription_id = EXCLUDED.razorpay_subscription_id,
          stripe_subscription_id = NULL,
          stripe_customer_id = NULL
      `);
    } catch (err) {
      log.error({ err }, 'Failed to upsert Razorpay subscription');
      return NextResponse.json({ error: 'Failed to record subscription', code: 'DB_ERROR' }, { status: 500 });
    }

    try {
      const { rows: subRows } = await db.execute(sql`
        SELECT billing_contact_email FROM public.subscriptions WHERE restaurant_id = ${restaurantId} LIMIT 1
      `);
      const billingContactEmail = (subRows[0] as { billing_contact_email: string | null } | undefined)?.billing_contact_email;
      if (billingContactEmail) {
        const { sendInvoiceNotificationEmail } = await import('@server/services/email.service');
        const { rows: planRows } = await db.execute(sql`SELECT name FROM plans WHERE id = ${planId} LIMIT 1`);
        const planName = (planRows[0] as { name: string } | undefined)?.name ?? 'Subscription';
        const now = new Date();
        const nextDate = new Date(now);
        nextDate.setMonth(nextDate.getMonth() + (billingCycle === 'annual' ? 12 : 1));
        await sendInvoiceNotificationEmail({
          to: billingContactEmail,
          restaurantName: planName,
          invoiceNumber: razorpayPaymentId,
          amount: '0.00',
          currency: subCurrency,
          periodStart: now.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }),
          periodEnd: nextDate.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }),
        }, restaurantId);
      }
    } catch (err) {
      log.warn({ err }, 'razorpay-verify: failed to send billing contact CC email');
    }

    return NextResponse.json({ ok: true, status: 'active' });
  })
);
