import { NextRequest, NextResponse } from "next/server";
import { requireAuth, getAdminAuditContext } from "@/lib/admin/auth";
import { userHasPermission } from "@/lib/admin/permissions";
import { db } from "@/lib/admin/db";
import { sendWebPushNotification } from "@/lib/push/vapid";

export const dynamic = "force-dynamic";

/**
 * POST /api/admin/push/send
 *
 * Manually sends a Web Push notification to all current subscribers for a
 * specific PUBLISHED blog post.
 *
 * Rules:
 *  - User MUST have "notifications.send" permission.
 *  - The post MUST be PUBLISHED. Draft/Archived posts are rejected.
 *  - This action NEVER fires automatically on publish — it is always initiated
 *    explicitly by an authorized administrator.
 *  - Expired subscriptions (HTTP 410/404) are automatically removed.
 *
 * Body:
 *  { postId: string, title?: string, body?: string }
 *
 * Response:
 *  { sent: number, failed: number, removed: number, total: number }
 */
export async function POST(req: NextRequest) {
  try {
    // Authentication & authorization
    const session = await requireAuth(req);
    if (!userHasPermission(session.user, "notifications.send")) {
      return NextResponse.json(
        { error: "Forbidden: You do not have permission to send push notifications." },
        { status: 403 }
      );
    }

    const body = await req.json().catch(() => ({}));
    const { postId } = body;

    if (!postId || typeof postId !== "string") {
      return NextResponse.json(
        { error: "postId is required." },
        { status: 400 }
      );
    }

    // Fetch the post and enforce PUBLISHED status
    const post = await db.getPostById(postId);
    if (!post) {
      return NextResponse.json({ error: "Post not found." }, { status: 404 });
    }
    if (post.status !== "PUBLISHED") {
      return NextResponse.json(
        {
          error: `Push notifications can only be sent for PUBLISHED posts. This post is ${post.status}.`,
        },
        { status: 422 }
      );
    }

    // Build notification payload
    const notifTitle =
      typeof body.title === "string" && body.title.trim()
        ? body.title.trim()
        : `New on Quto AI: ${post.title}`;

    const notifBody =
      typeof body.body === "string" && body.body.trim()
        ? body.body.trim()
        : post.excerpt?.slice(0, 160) || "A new article is available on Quto AI.";

    const notifUrl = `/blog/${post.slug}`;

    const payload = {
      title: notifTitle,
      body: notifBody,
      url: notifUrl,
      icon: "/images/bot-logo.png",
    };

    // Load all subscriptions
    const subscriptions = await db.getAllPushSubscriptions();
    const total = subscriptions.length;

    if (total === 0) {
      return NextResponse.json({
        ok: true,
        sent: 0,
        failed: 0,
        removed: 0,
        total: 0,
        message: "No subscribers to notify.",
      });
    }

    // Send to all — collect results
    let sent = 0;
    let failed = 0;
    let removed = 0;

    const results = await Promise.allSettled(
      subscriptions.map((sub) =>
        sendWebPushNotification(sub.endpoint, sub.keys, payload)
      )
    );

    for (const result of results) {
      if (result.status === "fulfilled") {
        const r = result.value;
        if (r.gone) {
          // Remove expired/invalid subscription
          await db.deletePushSubscription(r.endpoint);
          removed++;
        } else if (r.status >= 200 && r.status < 300) {
          sent++;
        } else {
          failed++;
        }
      } else {
        failed++;
      }
    }

    const auditCtx = await getAdminAuditContext(req);

    // Log push send audit event (Section 57: no secret keys recorded)
    await db.logContentEvent({
      actorId: session.user.id,
      actorName: session.user.name,
      actorEmail: session.user.email,
      actorRole: session.user.role,
      location: auditCtx.location || null,
      postId: post.id,
      postTitle: post.title,
      postSlug: post.slug,
      action: "PUSH_NOTIFICATION_SENT",
      details: {
        title: payload.title,
        subscriberCount: total,
        sent,
        failed,
        removed,
      },
    });

    return NextResponse.json({
      ok: true,
      sent,
      failed,
      removed,
      total,
      message: `Notification sent to ${sent} of ${total} subscriber${total === 1 ? "" : "s"}.${removed > 0 ? ` Removed ${removed} expired subscription${removed === 1 ? "" : "s"}.` : ""}`,
    });
  } catch (err: any) {
    const status = (err as any).status || 500;
    console.error("[POST /api/admin/push/send]", err);
    return NextResponse.json(
      { error: err.message || "Failed to send push notification." },
      { status }
    );
  }
}

/**
 * GET /api/admin/push/send
 * Returns the current subscriber count (for display in the admin UI modal).
 */
export async function GET(req: NextRequest) {
  try {
    await requireAuth(req);
    const count = await db.countPushSubscriptions();
    return NextResponse.json({ subscriberCount: count });
  } catch (err: any) {
    const status = (err as any).status || 500;
    return NextResponse.json(
      { error: err.message || "Failed to fetch subscriber count." },
      { status }
    );
  }
}
