import { NextRequest, NextResponse } from "next/server";
import { randomBytes } from "crypto";
import { db } from "@/lib/db";

/**
 * POST /api/auth/device-code/poll
 *
 * RFC 8628 Device Authorization Grant — Step 3.
 * CLI polls this with device_code until the user approves.
 *
 * Returns:
 * - 200 + {access_token, api_key} when approved
 * - 428 "authorization_pending" while waiting
 * - 410 "expired_token" if the code expired
 */
export async function POST(req: NextRequest) {
  try {
    const body = await req.json();
    const { device_code } = body;

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

    const record = await db.deviceCode.findUnique({
      where: { deviceCode: device_code },
      include: { user: { select: { id: true, email: true, name: true, plan: true } } },
    });

    if (!record) {
      return NextResponse.json(
        { error: "invalid_grant", error_description: "Unknown device code" },
        { status: 400 },
      );
    }

    // Check expiry
    if (new Date() > record.expires) {
      // Clean up expired code
      await db.deviceCode.delete({ where: { id: record.id } });
      return NextResponse.json(
        { error: "expired_token", error_description: "Device code expired. Please restart the flow." },
        { status: 410 },
      );
    }

    // Not yet approved
    if (!record.approved || !record.userId || !record.user) {
      return NextResponse.json(
        { error: "authorization_pending", error_description: "Waiting for user to approve." },
        { status: 428 },
      );
    }

    // Approved — generate API key for the CLI
    const apiKey = `lh_sk_${randomBytes(32).toString("base64url")}`;
    const prefix = apiKey.substring(0, 12) + "...";

    const createdKey = await db.apiKey.create({
      data: {
        userId: record.userId,
        name: `CLI Device (${new Date().toISOString().split("T")[0]})`,
        key: apiKey,
        prefix,
      },
    });

    // Update device code with the API key ID, then clean up
    await db.deviceCode.update({
      where: { id: record.id },
      data: { apiKeyId: createdKey.id },
    });

    // Clean up the device code (one-time use)
    await db.deviceCode.delete({ where: { id: record.id } });

    return NextResponse.json({
      access_token: apiKey,
      token_type: "Bearer",
      api_key: apiKey,
      user: {
        id: record.user.id,
        email: record.user.email,
        name: record.user.name,
        plan: record.user.plan,
      },
    });
  } catch {
    return NextResponse.json(
      { error: "server_error", error_description: "Internal server error" },
      { status: 500 },
    );
  }
}
