import { NextResponse } from "next/server";
import { sql } from "@/db";
import { requireFamily } from "@/lib/auth";
import { getRazorpayConfig, razorpayAuthHeader, RAZORPAY_API_BASE } from "@/lib/billing/config";

/**
 * POST /api/subscriptions/create
 *
 * Creates a Razorpay subscription for the caller's family and returns the
 * subscription_id + key_id for Razorpay Checkout. Grants NOTHING — entitlement
 * is applied only by the webhook (subscription.charged/activated).
 *
 * Security:
 *  - family_id comes from the session (requireFamily), never from the request
 *    body — so a user can only create a sub for their own family (IDOR-safe).
 *  - key_secret never leaves the server; only key_id is returned.
 */
export async function POST() {
  const auth = await requireFamily();
  if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });

  const familyId = auth.session!.familyId!;
  const userId = auth.session!.userId;

  let cfg;
  try {
    cfg = getRazorpayConfig();
  } catch (e) {
    return NextResponse.json({ error: String(e) }, { status: 500 });
  }

  // Resolve the plan row (must be seeded — see /api/admin/seed-plan).
  const planRows = await sql`
    SELECT id, razorpay_plan_id FROM subscription_plans
    WHERE razorpay_plan_id = ${cfg.planId} AND is_active = true
    LIMIT 1
  `;
  if (!planRows[0]) {
    return NextResponse.json(
      { error: "Plan not seeded. Run POST /api/admin/seed-plan first." },
      { status: 500 },
    );
  }
  const planRowId = planRows[0].id as string;

  // Inspect any existing non-terminal subscription for this family.
  const live = await sql`
    SELECT id, razorpay_subscription_id, status FROM family_subscriptions
    WHERE family_id = ${familyId}
      AND status IN ('created','authenticated','active','pending','halted')
    ORDER BY created_at DESC
    LIMIT 1
  `;
  if (live[0]) {
    const status = live[0].status as string;

    // Genuinely subscribed → block (they don't need a second subscription).
    if (status === "authenticated" || status === "active" || status === "pending") {
      return NextResponse.json(
        { error: "You already have an active subscription.", status },
        { status: 409 },
      );
    }

    // Abandoned checkout: a 'created' row whose payment never completed. The
    // Razorpay subscription is still payable, so REUSE it — reopen checkout for
    // the same sub instead of locking the user out forever.
    if (status === "created") {
      return NextResponse.json({
        subscriptionId: live[0].razorpay_subscription_id,
        keyId: cfg.keyId,
        reused: true,
      });
    }

    // 'halted' = retries exhausted, family already downgraded to free. Let them
    // re-subscribe: retire the halted row (leaves the partial unique index) so
    // a fresh subscription can be created below.
    if (status === "halted") {
      await sql`
        UPDATE family_subscriptions
        SET status = 'expired', ended_at = COALESCE(ended_at, NOW()), updated_at = NOW()
        WHERE id = ${live[0].id}
      `;
    }
  }

  // Create the subscription at Razorpay.
  let rzpSub: { id?: string; status?: string; error?: { description?: string } };
  try {
    const res = await fetch(`${RAZORPAY_API_BASE}/subscriptions`, {
      method: "POST",
      headers: {
        Authorization: razorpayAuthHeader(cfg),
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        plan_id: cfg.planId,
        total_count: 120, // ~10 yrs of monthly cycles; avoids auto-complete
        customer_notify: 1,
        quantity: 1,
        notes: { family_id: familyId, user_id: userId }, // correlation backup for webhook
      }),
    });
    rzpSub = await res.json();
    if (!res.ok || !rzpSub.id) {
      console.error("Razorpay create sub failed:", rzpSub);
      return NextResponse.json(
        { error: rzpSub?.error?.description || "Failed to create subscription" },
        { status: 502 },
      );
    }
  } catch (e) {
    console.error("Razorpay create sub error:", e);
    return NextResponse.json({ error: "Failed to reach payment provider" }, { status: 502 });
  }

  // Record our side as 'created'. The webhook drives all later state.
  try {
    await sql`
      INSERT INTO family_subscriptions
        (family_id, plan_id, razorpay_subscription_id, status)
      VALUES (${familyId}, ${planRowId}, ${rzpSub.id}, 'created')
    `;
  } catch (e) {
    // Unique index race (double-click) — treat as the existing-sub case.
    console.error("Insert family_subscriptions failed:", e);
    return NextResponse.json(
      { error: "Subscription already in progress for this family." },
      { status: 409 },
    );
  }

  return NextResponse.json({ subscriptionId: rzpSub.id, keyId: cfg.keyId });
}
