import Stripe from "stripe";
import { usePrisma } from "../../utils/prisma";
import { runDowngradeReconciliation } from "../../utils/downgrade-reconciliation";
import type { Plan } from "../../utils/plan-features";

/**
 * POST /api/stripe/webhook
 * Stripe Webhook – verarbeitet Subscription-Events.
 * Aktualisiert profiles.plan + stripe_* Felder + triggert Downgrade-Reconciliation.
 */
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig();
  const stripe = new Stripe(config.stripeSecretKey);

  const body = await readRawBody(event);
  const sig = getHeader(event, "stripe-signature");

  if (!body || !sig) {
    throw createError({
      statusCode: 400,
      message: "Missing body or signature",
    });
  }

  let stripeEvent: Stripe.Event;
  try {
    stripeEvent = stripe.webhooks.constructEvent(
      body,
      sig,
      config.stripeWebhookSecret,
    );
  } catch (err: any) {
    throw createError({
      statusCode: 400,
      message: `Webhook Error: ${err.message}`,
    });
  }

  const db = usePrisma();

  switch (stripeEvent.type) {
    case "checkout.session.completed": {
      const session = stripeEvent.data.object as Stripe.Checkout.Session;
      const userId = session.metadata?.user_id || session.client_reference_id;
      const plan = session.metadata?.plan || "legend";
      const newPlan = (
        plan === "legend" ? "legend" : plan === "pro" ? "pro" : "free"
      ) as Plan;

      if (userId) {
        const current = await db.profile.findUnique({
          where: { id: userId },
          select: { plan: true },
        });
        const fromPlan = (current?.plan ?? "free") as Plan;

        await db.profile.update({
          where: { id: userId },
          data: {
            plan: newPlan,
            stripeCustomerId: session.customer as string,
            stripeSubId: session.subscription as string,
          },
        });

        await runDowngradeReconciliation(userId, fromPlan, newPlan).catch(
          (err) => console.error("[stripe-webhook] reconciliation error:", err),
        );
      }
      break;
    }

    case "customer.subscription.updated": {
      const sub = stripeEvent.data.object as Stripe.Subscription;
      const customerId = sub.customer as string;

      const profile = await db.profile.findFirst({
        where: { stripeCustomerId: customerId },
        select: { id: true, plan: true },
      });

      if (profile) {
        const isActive = ["active", "trialing"].includes(sub.status);
        const newPlan = (isActive ? profile.plan : "free") as Plan;
        const fromPlan = profile.plan as Plan;

        await db.profile.update({
          where: { id: profile.id },
          data: {
            plan: newPlan,
            premiumUntil: sub.current_period_end
              ? new Date(sub.current_period_end * 1000)
              : null,
          },
        });

        await runDowngradeReconciliation(profile.id, fromPlan, newPlan).catch(
          (err) => console.error("[stripe-webhook] reconciliation error:", err),
        );
      }
      break;
    }

    case "customer.subscription.deleted": {
      const sub = stripeEvent.data.object as Stripe.Subscription;
      const customerId = sub.customer as string;

      const profile = await db.profile.findFirst({
        where: { stripeCustomerId: customerId },
        select: { id: true, plan: true },
      });

      if (profile) {
        const fromPlan = profile.plan as Plan;
        await db.profile.update({
          where: { id: profile.id },
          data: { plan: "free", premiumUntil: null },
        });

        await runDowngradeReconciliation(profile.id, fromPlan, "free").catch(
          (err) => console.error("[stripe-webhook] reconciliation error:", err),
        );
      }
      break;
    }
  }

  return { received: true };
});
