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, getRazorpayKeyId } from '@server/lib/razorpay';
import { getGatewayConfig } from '@server/services/gateway.service';
import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';
import { initDatabase } from '@server/db/init';
import { childLogger } from '@server/logger';

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

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 { planId, billingCycle } = _body;
    if (!planId) {
      return NextResponse.json({ error: 'planId is required', code: 'VALIDATION_ERROR' }, { status: 400 });
    }

    const cfg = await getGatewayConfig();
    if (!cfg.razorpayActive || !cfg.razorpayKeyId || !cfg.razorpayKeySecret) {
      return NextResponse.json({ error: 'Razorpay is not configured', code: 'GATEWAY_NOT_CONFIGURED' }, { status: 503 });
    }

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

    const currency = cfg.razorpayCurrency.toUpperCase();
    const restaurantId = req.session.restaurantId!;
    const cycle: 'monthly' | 'annual' = billingCycle === 'annual' ? 'annual' : 'monthly';

    const { rows: planRows } = await db.execute(sql`
      SELECT p.id, p.name,
             p.razorpay_plan_id_monthly, p.razorpay_plan_id_annual
      FROM public.plans p
      WHERE p.id = ${planId} AND p.is_active = true
      LIMIT 1
    `);
    const plan = planRows[0] as {
      id: string; name: string;
      razorpay_plan_id_monthly: string | null;
      razorpay_plan_id_annual: string | null;
    } | undefined;

    if (!plan) {
      return NextResponse.json({ error: 'Plan not found', code: 'NOT_FOUND' }, { status: 404 });
    }

    const razorpayPlanId = cycle === 'annual'
      ? plan.razorpay_plan_id_annual
      : plan.razorpay_plan_id_monthly;

    if (!razorpayPlanId) {
      return NextResponse.json({
        error: 'This plan has not been synced to Razorpay yet. Please ask your administrator to sync the plan.',
        code: 'RAZORPAY_PLAN_NOT_SYNCED',
      }, { status: 400 });
    }

    let subscription: { id: string };
    try {
      subscription = await (razorpay.subscriptions.create as unknown as (p: Record<string, unknown>) => Promise<{ id: string }>)({
        plan_id: razorpayPlanId,
        total_count: cycle === 'annual' ? 10 : 120,
        quantity: 1,
        notes: {
          restaurant_id: restaurantId,
          plan_id: planId,
          billing_cycle: cycle,
          currency,
        },
      });
    } catch (err) {
      log.error({ err }, 'Razorpay subscription creation failed');
      return NextResponse.json({ error: 'Failed to create Razorpay subscription', code: 'GATEWAY_ERROR' }, { status: 502 });
    }

    const keyId = await getRazorpayKeyId();

    return NextResponse.json({
      subscriptionId: subscription.id,
      keyId,
      currency,
      planName: plan.name,
    });
  })
);
