import { NextRequest, NextResponse } from "next/server";
import crypto from "crypto";
import { prisma } from "@/lib/prisma";

/**
 * Polar.sh webhook handler.
 *
 * In production, verify the webhook signature using Polar's webhook secret.
 * For development, we accept a direct ?userId=&tier= fallback for testing.
 */

export async function POST(req: NextRequest) {
  try {
    // Check for direct fallback query params (dev/testing only)
    const url = new URL(req.url);
    const directUserId = url.searchParams.get("userId");
    const directTier = url.searchParams.get("tier");

    if (directUserId && directTier) {
      // Production guard: never allow direct upgrades in production
      if (process.env.NODE_ENV === "production") {
        console.error("Direct upgrade blocked — not allowed in production");
        return NextResponse.json(
          { error: "Direct upgrades not allowed in production" },
          { status: 403 }
        );
      }
      return handleDirectUpgrade(directUserId, directTier);
    }

    // Production path: Parse Polar webhook event
    const rawBody = await req.text();

    // Verify webhook signature
    const signature = req.headers.get("webhook-id") || req.headers.get("polar-signature");
    const webhookSecret = process.env.POLAR_WEBHOOK_SECRET;

    if (webhookSecret) {
      if (!signature) {
        console.error("Polar webhook signature missing");
        return NextResponse.json(
          { error: "Missing webhook signature" },
          { status: 401 }
        );
      }

      const expectedSignature = crypto
        .createHmac("sha256", webhookSecret)
        .update(rawBody)
        .digest("hex");

      if (signature !== expectedSignature) {
        console.error("Polar webhook signature mismatch");
        return NextResponse.json(
          { error: "Invalid webhook signature" },
          { status: 401 }
        );
      }
    } else {
      console.warn("POLAR_WEBHOOK_SECRET not set — skipping signature verification (dev mode)");
    }

    const body = JSON.parse(rawBody);
    const event = body.type || body.event;

    if (!event) {
      return NextResponse.json(
        { error: "Missing event type" },
        { status: 400 }
      );
    }

    // Handle checkout.completed event
    if (
      event === "checkout.completed" ||
      event === "checkout.updated"
    ) {
      const checkout = body.data?.checkout || body.data;
      if (!checkout) {
        return NextResponse.json(
          { error: "Missing checkout data" },
          { status: 400 }
        );
      }

      const metadataType = checkout.metadata?.type;
      const customerEmail = checkout.customer?.email;

      // --- Course purchase flow ---
      if (metadataType === "course_purchase") {
        const courseSlug = checkout.metadata?.course_slug;
        if (!courseSlug) {
          return NextResponse.json(
            { error: "Missing course_slug in metadata for course_purchase" },
            { status: 400 }
          );
        }
        if (!customerEmail) {
          return NextResponse.json(
            { error: "Missing customer email for course_purchase" },
            { status: 400 }
          );
        }
        return handleCoursePurchase(customerEmail, courseSlug);
      }

      // --- Learn subscription flow ---
      if (metadataType === "learn_subscription") {
        if (!customerEmail) {
          return NextResponse.json(
            { error: "Missing customer email for learn_subscription" },
            { status: 400 }
          );
        }
        return handleLearnSubscription(customerEmail, checkout);
      }

      // --- Fallback: premium/pro upgrade (existing logic) ---
      const userId = checkout.metadata?.userId;
      const priceId = checkout.product?.priceId ||
                       checkout.productPrice?.id ||
                       checkout.metadata?.priceId;

      if (!userId) {
        return NextResponse.json(
          { error: "Missing userId in metadata" },
          { status: 400 }
        );
      }

      // Determine tier from priceId or product metadata
      let tier: "premium" | "pro" = "premium";
      if (priceId?.includes("pro") || checkout.metadata?.tier === "pro") {
        tier = "pro";
      }

      return applyUpgrade(userId, tier);
    }

    // Handle subscription.cancelled and subscription.revoked events
    if (event === "subscription.cancelled" || event === "subscription.revoked") {
      return handleSubscriptionCancelled(body.data);
    }

    // Acknowledge other events silently
    return NextResponse.json({ received: true });
  } catch (error) {
    console.error("Polar webhook error:", error);
    return NextResponse.json(
      { error: "Webhook processing failed" },
      { status: 500 }
    );
  }
}

async function handleDirectUpgrade(userId: string, tier: string) {
  if (tier !== "premium" && tier !== "pro") {
    return NextResponse.json(
      { error: "Invalid tier. Must be 'premium' or 'pro'." },
      { status: 400 }
    );
  }
  return applyUpgrade(userId, tier as "premium" | "pro");
}

async function applyUpgrade(userId: string, tier: "premium" | "pro") {
  const user = await prisma.user.findUnique({ where: { id: userId } });
  if (!user) {
    return NextResponse.json({ error: "User not found" }, { status: 404 });
  }

  const trialEndsAt = new Date();
  trialEndsAt.setDate(trialEndsAt.getDate() + 7);

  const updateData: Record<string, unknown> = {
    trialEndsAt,
  };

  if (tier === "pro") {
    updateData.isPro = true;
    updateData.isPremium = false; // Pro supersedes Premium
  } else {
    updateData.isPremium = true;
  }

  await prisma.user.update({
    where: { id: userId },
    data: updateData,
  });

  return NextResponse.json({
    success: true,
    tier,
    trialEndsAt,
  });
}

/**
 * Handle a course_purchase checkout.
 * Looks up the user by email, finds the LearnCourse by slug,
 * and creates (or re-activates) a LearnEnrollment with purchaseType='one_time'.
 */
async function handleCoursePurchase(customerEmail: string, courseSlug: string) {
  // Find the user by email
  const user = await prisma.user.findUnique({ where: { email: customerEmail } });
  if (!user) {
    return NextResponse.json(
      { error: "User not found for email" },
      { status: 404 }
    );
  }

  // Find the course by slug
  const course = await prisma.learnCourse.findUnique({ where: { slug: courseSlug } });
  if (!course) {
    return NextResponse.json(
      { error: "Course not found" },
      { status: 404 }
    );
  }

  // Upsert enrollment: create or re-activate on re-purchase
  await prisma.learnEnrollment.upsert({
    where: {
      userId_courseId: { userId: user.id, courseId: course.id },
    },
    create: {
      userId: user.id,
      courseId: course.id,
      purchaseType: "one_time",
      progress: 0,
      startedAt: new Date(),
    },
    update: {
      purchaseType: "one_time",
      completed: false,
      progress: 0,
      completedAt: null,
      startedAt: new Date(),
    },
  });

  return NextResponse.json({
    success: true,
    type: "course_purchase",
    userId: user.id,
    courseId: course.id,
    courseSlug,
  });
}

/**
 * Handle a learn_subscription checkout.
 * Looks up the user by email and creates/updates a LearnSubscription record.
 * Uses Polar subscription data for period management.
 */
async function handleLearnSubscription(customerEmail: string, checkout: any) {
  // Find the user by email
  const user = await prisma.user.findUnique({ where: { email: customerEmail } });
  if (!user) {
    return NextResponse.json(
      { error: "User not found for email" },
      { status: 404 }
    );
  }

  // Extract subscription details from checkout data
  const polarSubId =
    checkout.subscription?.id ||
    checkout.metadata?.subscriptionId ||
    null;

  const now = new Date();
  const currentPeriodStart = checkout.subscription?.currentPeriodStart
    ? new Date(checkout.subscription.currentPeriodStart)
    : now;
  const currentPeriodEnd = checkout.subscription?.currentPeriodEnd
    ? new Date(checkout.subscription.currentPeriodEnd)
    : new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); // Default 30 days

  // Upsert subscription record per user (one active subscription per user)
  if (polarSubId) {
    await prisma.learnSubscription.upsert({
      where: { polarSubId },
      create: {
        userId: user.id,
        polarSubId,
        status: "active",
        currentPeriodStart,
        currentPeriodEnd,
      },
      update: {
        userId: user.id,
        status: "active",
        currentPeriodStart,
        currentPeriodEnd,
        cancelledAt: null,
      },
    });
  } else {
    // No polarSubId: check if user already has a subscription and update it
    const existing = await prisma.learnSubscription.findFirst({
      where: { userId: user.id },
      orderBy: { createdAt: "desc" },
    });

    if (existing) {
      await prisma.learnSubscription.update({
        where: { id: existing.id },
        data: {
          status: "active",
          currentPeriodStart,
          currentPeriodEnd,
          cancelledAt: null,
        },
      });
    } else {
      await prisma.learnSubscription.create({
        data: {
          userId: user.id,
          status: "active",
          currentPeriodStart,
          currentPeriodEnd,
        },
      });
    }
  }

  // Also update the User's premium status to match the active subscription
  await prisma.user.update({
    where: { id: user.id },
    data: {
      isPremium: true,
      trialEndsAt: currentPeriodEnd,
    },
  });

  return NextResponse.json({
    success: true,
    type: "learn_subscription",
    userId: user.id,
  });
}

/**
 * Handle a subscription.cancelled or subscription.revoked event.
 * Sets the LearnSubscription status to 'cancelled' and removes the user's isPremium flag.
 */
async function handleSubscriptionCancelled(data: any) {
  // Extract the Polar subscription ID from the event data
  const polarSubId =
    data?.id ||
    data?.subscription?.id ||
    data?.metadata?.subscriptionId ||
    null;

  if (!polarSubId) {
    return NextResponse.json(
      { error: "Missing subscription ID in event data" },
      { status: 400 }
    );
  }

  // Find the LearnSubscription by the Polar subscription ID
  const subscription = await prisma.learnSubscription.findUnique({
    where: { polarSubId },
  });

  if (!subscription) {
    return NextResponse.json(
      { error: "LearnSubscription not found for polarSubId" },
      { status: 404 }
    );
  }

  // Mark the subscription as cancelled
  await prisma.learnSubscription.update({
    where: { id: subscription.id },
    data: {
      status: "cancelled",
      cancelledAt: new Date(),
    },
  });

  // Remove the user's premium flag
  await prisma.user.update({
    where: { id: subscription.userId },
    data: {
      isPremium: false,
    },
  });

  return NextResponse.json({
    success: true,
    type: "subscription_cancelled",
    userId: subscription.userId,
  });
}
