import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
import { corePool } from "@/lib/db/mysql";

export const runtime = "nodejs";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string);

export async function POST(req: NextRequest) {
  const sig = req.headers.get("stripe-signature");
  const body = await req.text();

  if (!sig) {
    return NextResponse.json({ error: "missing_signature" }, { status: 400 });
  }

  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET as string
    );
  } catch (err) {
    console.error("Webhook signature error:", err);
    return NextResponse.json({ error: "invalid_signature" }, { status: 400 });
  }

  try {
    switch (event.type) {
      case "checkout.session.completed":
        await handleCheckoutCompleted(event.data.object as Stripe.Checkout.Session);
        break;

      case "customer.subscription.updated":
      case "customer.subscription.deleted":
        await handleSubscriptionUpdate(event.data.object as Stripe.Subscription);
        break;
    }

    return NextResponse.json({ received: true });
  } catch (err) {
    console.error("Webhook processing error:", err);
    return NextResponse.json({ error: "webhook_failed" }, { status: 500 });
  }
}

/* ---------------- HANDLERS ---------------- */

async function handleCheckoutCompleted(session: Stripe.Checkout.Session) {
  if (session.mode === "payment") {
    await handleOneShotPayment(session);
  }

  if (session.mode === "subscription") {
    await handleSubscriptionCheckout(session);
  }
}

async function handleOneShotPayment(session: Stripe.Checkout.Session) {
  const jobId = Number(session.metadata?.job_id);
  const plan = session.metadata?.plan;

  if (!jobId || !plan) {
    throw new Error("missing_metadata");
  }

  const priceId = session.line_items?.data?.[0]?.price?.id;

  const allowedPrices = [
    process.env.STRIPE_PRICE_ESSENTIELLE,
    process.env.STRIPE_PRICE_ENGAGEE,
  ];

  if (!allowedPrices.includes(priceId || "")) {
    throw new Error("invalid_price");
  }

  await corePool.query(
    `
    UPDATE jobs
    SET status = 'published',
        published_at = NOW(),
        paid_plan = ?
    WHERE id = ?
    `,
    [plan, jobId]
  );
}

async function handleSubscriptionCheckout(session: Stripe.Checkout.Session) {
  const companyId = Number(session.metadata?.company_id);
  const subscriptionId = session.subscription as string;

  if (!companyId || !subscriptionId) {
    throw new Error("missing_subscription_metadata");
  }

  const subscription = await stripe.subscriptions.retrieve(subscriptionId);

  const allowedPrices = [
    process.env.STRIPE_PRICE_SENIOR_READY_MONTHLY,
    process.env.STRIPE_PRICE_SENIOR_READY_YEARLY,
  ];

  const priceId = subscription.items.data[0]?.price.id;

  if (!allowedPrices.includes(priceId || "")) {
    throw new Error("invalid_subscription_price");
  }

  await corePool.query(
    `
    INSERT INTO subscriptions (
      company_id,
      stripe_subscription_id,
      stripe_customer_id,
      status,
      current_period_end
    )
    VALUES (?, ?, ?, 'active', FROM_UNIXTIME(?))
    ON DUPLICATE KEY UPDATE
      status = 'active',
      current_period_end = FROM_UNIXTIME(?)
    `,
    [
      companyId,
      subscription.id,
      subscription.customer as string,
      subscription.current_period_end,
      subscription.current_period_end,
    ]
  );

  await corePool.query(
    `
    UPDATE companies
    SET plan_type = 'senior_ready',
        plan_status = 'active',
        banner_enabled = 1
    WHERE id = ?
    `,
    [companyId]
  );
}

async function handleSubscriptionUpdate(subscription: Stripe.Subscription) {
  const companyId = Number(subscription.metadata?.company_id);

  if (!companyId) return;

  if (subscription.status !== "active") {
    await corePool.query(
      `
      UPDATE companies
      SET plan_status = 'suspended'
      WHERE id = ?
      `,
      [companyId]
    );

    await corePool.query(
      `
      UPDATE jobs
      SET status = 'expired'
      WHERE company_id = ?
        AND status = 'published'
      `,
      [companyId]
    );
  }
}
