/**
 * POST /api/webhook
 *
 * Stripe webhook handler. On successful payment, signs a
 * license token and emails it to the customer.
 */

import type { Context } from "hono";
import type { Env } from "../env.d";
import Stripe from "stripe";
import { signLicenseToken } from "../lib/sign-token";
import { sendEmail } from "../lib/send-email";
import { licenseEmail } from "../templates/license-email";

/** Maps pricing plan to token parameters. */
const PLAN_CONFIG: Record<string, { tier: "standard" | "enterprise"; seats: number; days: number; label: string }> = {
  individual: { tier: "standard", seats: 1, days: 365, label: "Individual" },
  team: { tier: "enterprise", seats: 25, days: 365, label: "Team" },
  enterprise: { tier: "enterprise", seats: 9999, days: 365, label: "Enterprise" },
};

export async function handleWebhook(c: Context): Promise<Response> {
  const env = c.env as Env;
  const stripe = new Stripe(env.STRIPE_SECRET_KEY);

  // Verify webhook signature using the raw body
  const rawBody = await c.req.text();
  const signature = c.req.header("stripe-signature");

  if (!signature) {
    return c.json({ error: "Missing stripe-signature header" }, 400);
  }

  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(
      rawBody,
      signature,
      env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    console.error("Webhook signature verification failed:", err);
    return c.json({ error: "Invalid signature" }, 400);
  }

  // Only handle successful checkouts
  if (event.type !== "checkout.session.completed") {
    return c.json({ received: true });
  }

  const session = event.data.object as Stripe.Checkout.Session;
  const plan = session.metadata?.plan;
  const email = session.customer_email;

  if (!plan || !email) {
    console.error("Webhook missing plan or email:", { plan, email });
    return c.json({ error: "Missing plan or email in session" }, 400);
  }

  const config = PLAN_CONFIG[plan];
  if (!config) {
    console.error("Unknown plan in webhook:", plan);
    return c.json({ error: `Unknown plan: ${plan}` }, 400);
  }

  // Sign the license token
  const slug = email.split("@")[0].replace(/[^a-z0-9]+/gi, "-").toLowerCase();
  const result = await signLicenseToken(
    {
      sub: slug,
      tier: config.tier,
      seats: config.seats,
      days: config.days,
    },
    env.SIGNING_PRIVATE_KEY
  );

  // Email the license to the customer
  try {
    await sendEmail(
      {
        to: email,
        subject: `Your StyloBridge ${config.label} License Key`,
        html: licenseEmail({
          planName: config.label,
          token: result.token,
          expires: new Date(result.expires).toLocaleDateString("en-US", {
            year: "numeric",
            month: "long",
            day: "numeric",
          }),
        }),
      },
      env.RESEND_API_KEY
    );
  } catch (err) {
    console.error("Failed to send license email:", err);
    // Return 500 so Stripe retries the webhook
    return c.json({ error: "Failed to send email" }, 500);
  }

  return c.json({ received: true, emailed: true });
}
