import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { prisma as db } from "@/lib/db";
import { logger } from "@/lib/logger";
import { rateLimiters } from "@/lib/rate-limiter";
import { stripe, getOrCreateCustomer } from "@/lib/stripe";
import { z } from "zod";
import { withCSRF } from "@/lib/csrf";
import { getDataSource } from "@/lib/data-source";
import { convexQuery, convexMutation } from "@/lib/convex-client";

// Validation schema
const onboardingSchema = z.object({
  goals: z.array(z.string()),
  integrations: z.object({
    hasCalendar: z.string().optional(),
    calendarSystem: z.string().optional(),
    hasWhatsApp: z.string().optional(),
    teamSize: z.string().optional(),
    otherGoal: z.string().optional(),
  }),
  userId: z.string().optional(),
  email: z.string().email().optional(),
  selectedPackage: z.string().optional(),
});

// Tier to Stripe price mapping (you'll need to update these with actual Stripe price IDs)
const TIER_PRICE_MAP: Record<string, string> = {
  tier1: process.env.STRIPE_PRICE_TIER1_MONTHLY || "price_tier1_monthly",
  tier2: process.env.STRIPE_PRICE_TIER2_MONTHLY || "price_tier2_monthly",
  tier3: process.env.STRIPE_PRICE_TIER3_MONTHLY || "price_tier3_monthly",
  tier4: process.env.STRIPE_PRICE_TIER4_MONTHLY || "price_tier4_monthly",
  tier5: process.env.STRIPE_PRICE_TIER5_MONTHLY || "price_tier5_monthly",
};

async function handler(req: NextRequest) {
  try {
    // Check rate limiting
    const identifier = req.headers.get("x-forwarded-for") || "anonymous";
    const rateLimitResult = await rateLimiters.signup.limit(identifier);

    if (!rateLimitResult.success) {
      logger.warn("Rate limit exceeded for onboarding submission", {
        identifier,
      });
      return NextResponse.json(
        { error: "Too many requests. Please try again later." },
        { status: 429 },
      );
    }

    // Get authenticated session
    const session = await auth();
    if (!session?.user?.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Parse and validate request body
    const body = await req.json();
    const validation = onboardingSchema.safeParse(body);

    if (!validation.success) {
      logger.warn("Invalid onboarding data", {
        errors: validation.error.errors,
        userId: session.user.id,
      });
      return NextResponse.json(
        { error: "Invalid data", details: validation.error.errors },
        { status: 400 },
      );
    }

    const data = validation.data;
    const selectedPackage = data.selectedPackage || "tier2";

    // Get user from database
    const user = await db.user.findUnique({
      where: { id: session.user.id },
    });

    if (!user) {
      return NextResponse.json({ error: "User not found" }, { status: 404 });
    }

    // Update user with goals and mark onboarding complete
    await db.user.update({
      where: { id: session.user.id },
      data: {
        goals: data.goals,
        selectedPackage: selectedPackage,
        onboardingComplete: true,
        updatedAt: new Date(),
      },
    });

    // Mirror to Convex (fire-and-forget, non-fatal)
    if (getDataSource("auth") === "convex") {
      Promise.resolve().then(async () => {
        try {
          const email = session.user?.email;
          if (email) {
            await convexMutation("auth/mutations:setOnboardingCompleteNoAuth", {
              email,
              onboardingComplete: true,
              trialEndsAt: null,
            });
          }
        } catch {
          // non-fatal
        }
      });
    }

    // Create or retrieve Stripe customer
    let stripeCustomerId = user.stripeCustomerId;

    if (!stripeCustomerId) {
      const customer = await getOrCreateCustomer({
        email: user.email,
        name: user.name,
        metadata: {
          userId: user.id,
          companyName: user.companyName || "",
          industry: user.industry || "",
        },
      });
      stripeCustomerId = customer.id;

      // Update user with Stripe customer ID
      await db.user.update({
        where: { id: user.id },
        data: { stripeCustomerId },
      });
    }

    // Create Stripe subscription with 14-day trial
    const priceId = TIER_PRICE_MAP[selectedPackage];

    try {
      const subscription = await stripe.subscriptions.create({
        customer: stripeCustomerId,
        items: [{ price: priceId }],
        trial_period_days: 14,
        metadata: {
          userId: user.id,
          tierId: selectedPackage,
        },
        payment_settings: {
          save_default_payment_method: "on_subscription",
        },
        trial_settings: {
          end_behavior: {
            missing_payment_method: "pause",
          },
        },
      });

      // Save subscription to database
      await db.subscription.create({
        data: {
          userId: user.id,
          stripeCustomerId: stripeCustomerId,
          stripeSubscriptionId: subscription.id,
          stripePriceId: priceId,
          tierId: selectedPackage,
          status: "trialing",
          billingPeriod: "monthly",
          currentPeriodEnd: new Date(subscription.current_period_end * 1000),
          trialEndsAt: subscription.trial_end
            ? new Date(subscription.trial_end * 1000)
            : null,
        },
      });

      logger.info("Subscription created successfully", {
        userId: user.id,
        subscriptionId: subscription.id,
        tierId: selectedPackage,
      });
    } catch (stripeError) {
      logger.error("Failed to create Stripe subscription", stripeError);
      // Continue without subscription - user can set it up later
    }

    // Log audit event
    await db.auditLog.create({
      data: {
        userId: session.user.id,
        type: "onboarding_complete",
        action: "User completed onboarding",
        success: true,
        ip: identifier,
        userAgent: req.headers.get("user-agent") || undefined,
        metadata: {
          goals: data.goals,
          selectedPackage,
        },
      },
    });

    logger.info("Onboarding completed successfully", {
      userId: session.user.id,
      goals: data.goals,
      package: selectedPackage,
    });

    return NextResponse.json({
      success: true,
      message: "Onboarding completed successfully",
      subscriptionId: user.stripeCustomerId,
    });
  } catch (error) {
    logger.error("Error during onboarding", error);
    return NextResponse.json(
      { error: "Failed to complete onboarding" },
      { status: 500 },
    );
  }
}

export const POST = withCSRF(handler);
