/**
 * API Keys Management API
 *
 * GET - Get all API keys for user (without encrypted keys)
 * POST - Create new API key (returns plaintext once, with CSRF + rate limit)
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import { apiKeyManagementService } from "@/lib/services/api-key-management.service";
import { validateCSRFToken } from "@/lib/csrf";
import { rateLimiters, applyRateLimit } from "@/lib/rate-limiter";
import { logger } from "@/lib/logger";
import validator from "validator";

const scopedLogger = logger.scope("APIKeysAPI");

/**
 * GET /api/dashboard/api-keys
 * Returns all API keys for the user (without encrypted key values)
 */
export async function GET(request: NextRequest) {
  try {
    // Authenticate user
    const user = await getAuthenticatedUser(request, auth);

    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    // Get all API keys for user
    const apiKeys = await apiKeyManagementService.getUserAPIKeys(user.userId);

    scopedLogger.info("API keys retrieved", {
      userId: user.userId,
      count: apiKeys.length,
    });

    return NextResponse.json({
      success: true,
      apiKeys,
      totalCount: apiKeys.length,
    });
  } catch (error) {
    scopedLogger.error("Failed to get API keys", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}

/**
 * POST /api/dashboard/api-keys
 * Create a new API key
 * Returns plaintext key ONCE - user must save it
 * Requires CSRF token and rate limiting
 */
export async function POST(request: NextRequest) {
  try {
    // Rate limiting - Very strict for API key creation (5 per hour)
    const rateLimitResponse = await applyRateLimit(
      request,
      rateLimiters.register, // Reusing register limiter (5 per hour)
    );

    if (rateLimitResponse) {
      return rateLimitResponse;
    }

    // Authenticate user
    const user = await getAuthenticatedUser(request, auth);

    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    // CSRF protection
    if (!validateCSRFToken(request)) {
      scopedLogger.warn("CSRF validation failed", { userId: user.userId });
      return NextResponse.json(
        { success: false, error: "Invalid CSRF token" },
        { status: 403 },
      );
    }

    // Parse request body
    const body = await request.json();
    const { service, keyName, apiKey, expiresAt } = body;

    // Validation
    const errors: string[] = [];

    if (!service || typeof service !== "string" || service.trim().length < 2) {
      errors.push("Service name is required (minimum 2 characters)");
    }

    if (!keyName || typeof keyName !== "string" || keyName.trim().length < 2) {
      errors.push("Key name is required (minimum 2 characters)");
    }

    if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length < 10) {
      errors.push("API key is required (minimum 10 characters)");
    }

    // Sanitize service and keyName
    const sanitizedService = service ? validator.escape(service.trim()) : "";
    const sanitizedKeyName = keyName ? validator.escape(keyName.trim()) : "";

    // Validate expiration date if provided
    let expirationDate: Date | undefined;
    if (expiresAt) {
      expirationDate = new Date(expiresAt);
      if (isNaN(expirationDate.getTime())) {
        errors.push("Invalid expiration date format");
      } else if (expirationDate <= new Date()) {
        errors.push("Expiration date must be in the future");
      }
    }

    if (errors.length > 0) {
      return NextResponse.json(
        { success: false, error: errors.join(", "), errors },
        { status: 400 },
      );
    }

    // Create API key
    const result = await apiKeyManagementService.createAPIKey(user.userId, {
      service: sanitizedService,
      keyName: sanitizedKeyName,
      apiKey: apiKey.trim(),
      expiresAt: expirationDate,
    });

    scopedLogger.info("API key created", {
      userId: user.userId,
      keyId: result.key.id,
      service: sanitizedService,
    });

    return NextResponse.json(
      {
        success: true,
        key: result.key,
        plaintextKey: result.plaintextKey, // Returned ONCE only
        warning: "Save this key now - it will not be shown again",
        message: "API key created successfully",
      },
      { status: 201 },
    );
  } catch (error: any) {
    scopedLogger.error("Failed to create API key", error);

    // Handle duplicate key name error
    if (error.message?.includes("already exists")) {
      return NextResponse.json(
        { success: false, error: error.message },
        { status: 409 },
      );
    }

    return NextResponse.json(
      { success: false, error: "Failed to create API key" },
      { status: 500 },
    );
  }
}
