import { NextResponse } from "next/server"
import { eq } from "drizzle-orm"
import { stripe } from "@/lib/stripe/client"
import { db } from "@/lib/db"
import { profiles, rent_payments } from "@/lib/db/schema"
import type Stripe from "stripe"

export async function POST(request: Request) {
  const body = await request.text()
  const sig = request.headers.get("stripe-signature")!

  let event: Stripe.Event

  try {
    event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!)
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : "Unknown error"
    return NextResponse.json({ error: `Webhook error: ${message}` }, { status: 400 })
  }

  // Webhooks are not user-scoped: they identify the target row by the id /
  // customer id stored in Stripe metadata. `user_id` is the current key;
  // `supabase_user_id` is read as a fallback so subscriptions/checkouts created
  // before the rename keep resolving. (Both hold the same app user id.)
  switch (event.type) {
    case "checkout.session.completed": {
      const session = event.data.object as Stripe.Checkout.Session
      const userId = session.metadata?.user_id ?? session.metadata?.supabase_user_id
      const plan = session.metadata?.plan

      if (!userId || !plan) break

      if (session.mode === "payment") {
        // Lifetime plan
        await db
          .update(profiles)
          .set({ plan: "lifetime", subscription_status: "active" })
          .where(eq(profiles.id, userId))
      }
      break
    }

    case "customer.subscription.created":
    case "customer.subscription.updated": {
      const subscription = event.data.object as Stripe.Subscription
      const userId = subscription.metadata?.user_id ?? subscription.metadata?.supabase_user_id
      const plan = subscription.metadata?.plan

      if (!userId) break

      await db
        .update(profiles)
        .set({
          plan: (plan ?? "starter") as typeof profiles.$inferSelect.plan,
          stripe_subscription_id: subscription.id,
          subscription_status: subscription.status,
          plan_expires_at: (subscription as any).current_period_end
            ? new Date((subscription as any).current_period_end * 1000).toISOString()
            : null,
        })
        .where(eq(profiles.id, userId))
      break
    }

    case "customer.subscription.deleted": {
      const subscription = event.data.object as Stripe.Subscription
      const userId = subscription.metadata?.user_id ?? subscription.metadata?.supabase_user_id

      if (!userId) break

      await db
        .update(profiles)
        .set({
          plan: "starter",
          stripe_subscription_id: null,
          subscription_status: "canceled",
          plan_expires_at: null,
        })
        .where(eq(profiles.id, userId))
      break
    }

    case "invoice.payment_failed": {
      const invoice = event.data.object as Stripe.Invoice
      const customerId = invoice.customer as string

      await db
        .update(profiles)
        .set({ subscription_status: "past_due" })
        .where(eq(profiles.stripe_customer_id, customerId))
      break
    }

    // Rent payment completed via payment link
    case "payment_intent.succeeded": {
      const intent = event.data.object as Stripe.PaymentIntent
      if (intent.metadata?.type !== "rent_payment") break

      const paymentId = intent.metadata?.payment_id
      if (paymentId) {
        await db
          .update(rent_payments)
          .set({
            status: "paid",
            paid_date: new Date().toISOString().slice(0, 10),
            stripe_payment_intent_id: intent.id,
          })
          .where(eq(rent_payments.id, paymentId))
      }
      break
    }
  }

  return NextResponse.json({ received: true })
}
