import { NextRequest, NextResponse } from "next/server";
import { eq } from "drizzle-orm";
import type Stripe from "stripe";
import { db, schema } from "@/lib/db";
import { getStripe } from "@/lib/stripe";

/**
 * Stripe webhook : `checkout.session.completed` → marque la facture payée et
 * fait avancer le dossier.
 *
 * - Acompte payé (dossier en `formulaire` ou `en_attente_paiement`)
 *   → dossier passe `acompte_paye`, facture `payee`.
 * - Solde payé (dossier en `solde_a_payer`)
 *   → dossier passe `termine`, facture `payee`.
 *
 * Le secret est configuré côté Stripe Dashboard, on l'attend dans
 * `STRIPE_WEBHOOK_SECRET`. La route est publique (pas d'auth) ; la vérif
 * vient de la signature Stripe.
 */

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

export async function POST(req: NextRequest) {
  const stripe = getStripe();
  const secret = process.env.STRIPE_WEBHOOK_SECRET;

  if (!stripe || !secret) {
    return NextResponse.json(
      { error: "Stripe non configuré côté serveur." },
      { status: 503 }
    );
  }

  const sig = req.headers.get("stripe-signature");
  if (!sig) {
    return NextResponse.json({ error: "Missing signature." }, { status: 400 });
  }

  const rawBody = await req.text();

  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(rawBody, sig, secret);
  } catch (err) {
    console.error("[stripe-webhook] Signature invalide :", err);
    return NextResponse.json(
      { error: "Signature invalide." },
      { status: 400 }
    );
  }

  if (event.type !== "checkout.session.completed") {
    // On ignore tous les autres events ; renvoyer 200 pour que Stripe ne
    // ré-essaie pas indéfiniment.
    return NextResponse.json({ received: true, ignored: event.type });
  }

  const session = event.data.object as Stripe.Checkout.Session;

  // On a besoin de l'invoiceId stocké dans metadata
  const invoiceId = session.metadata?.invoiceId;
  const dossierId = session.metadata?.dossierId;
  if (!invoiceId || !dossierId) {
    console.warn("[stripe-webhook] metadata manquante", session.id);
    return NextResponse.json({ received: true, warning: "metadata" });
  }

  if (session.payment_status !== "paid") {
    return NextResponse.json({ received: true, warning: "not paid" });
  }

  const now = new Date();

  try {
    // 1. facture → payee
    const [invoice] = await db
      .update(schema.invoice)
      .set({
        status: "payee",
        paidAt: now,
        paymentMethod: "CB",
        paymentReference: session.id,
        updatedAt: now,
      })
      .where(eq(schema.invoice.id, invoiceId))
      .returning();

    if (!invoice) {
      console.warn("[stripe-webhook] Invoice introuvable", invoiceId);
      return NextResponse.json({ received: true, warning: "no-invoice" });
    }

    // 2. dossier → avance selon le statut courant
    const [dossier] = await db
      .select()
      .from(schema.dossier)
      .where(eq(schema.dossier.id, dossierId))
      .limit(1);

    if (dossier) {
      let newStatus: typeof dossier.status | null = null;
      if (
        dossier.status === "formulaire" ||
        dossier.status === "en_attente_paiement"
      ) {
        newStatus = "acompte_paye";
      } else if (dossier.status === "solde_a_payer") {
        newStatus = "termine";
      }

      if (newStatus) {
        await db
          .update(schema.dossier)
          .set({ status: newStatus, updatedAt: now })
          .where(eq(schema.dossier.id, dossierId));
      }

      await db.insert(schema.activityLog).values({
        dossierId,
        actorId: dossier.clientId,
        action:
          newStatus === "termine"
            ? "solde_paye_stripe"
            : "acompte_paye_stripe",
        payload: {
          invoiceId,
          invoiceNumber: invoice.number,
          amountCents: invoice.amountCents,
          sessionId: session.id,
        },
      });
    }

    return NextResponse.json({ received: true });
  } catch (err) {
    console.error("[stripe-webhook] DB error :", err);
    // 500 → Stripe va re-livrer
    return NextResponse.json({ error: "DB error" }, { status: 500 });
  }
}
