/**
 * Stripe Keys API
 *
 * GET /api/staff/settings/stripe-keys - Get masked keys for an organization
 * POST /api/staff/settings/stripe-keys - Save Stripe keys for an organization
 * DELETE /api/staff/settings/stripe-keys - Delete Stripe keys for an organization
 *
 * Only accessible to ADMIN and SUPER_ADMIN staff.
 */

import { NextRequest, NextResponse } from "next/server";
import { validateStaffSession } from "@/lib/staff-session";
import { stripeKeysService } from "@/lib/services/stripe-keys.service";
import { prisma } from "@/lib/db";
import { logger } from "@/lib/logger";
import { z } from "zod";
import { getDataSource } from "@/lib/data-source";

/**
 * Helper to get organization ID for current staff member
 * Staff members are linked via their email to users, who own organizations
 */
async function getStaffOrganizationId(
  staffEmail: string,
): Promise<string | null> {
  // When billing data source is convex, still resolve org via Prisma
  // since org membership is in Prisma during migration
  const _ds = getDataSource("billing");
  void _ds;

  const user = await prisma.users.findUnique({
    where: { email: staffEmail },
    select: { id: true },
  });

  if (!user) {
    const membership = await prisma.organization_members.findFirst({
      where: {
        user: { email: staffEmail },
      },
      select: { organizationId: true },
    });
    return membership?.organizationId || null;
  }

  const ownedOrg = await prisma.organizations.findUnique({
    where: { ownerId: user.id },
    select: { id: true },
  });

  if (ownedOrg) {
    return ownedOrg.id;
  }

  const membership = await prisma.organization_members.findFirst({
    where: { userId: user.id },
    select: { organizationId: true },
  });

  return membership?.organizationId || null;
}

// Validation schemas
const saveKeysSchema = z.object({
  organizationId: z.string().optional(),
  secretKey: z
    .string()
    .min(10, "Secret key is required")
    .refine(
      (key) => key.startsWith("sk_test_") || key.startsWith("sk_live_"),
      "Secret key must start with sk_test_ or sk_live_",
    ),
  publishableKey: z
    .string()
    .min(10, "Publishable key is required")
    .refine(
      (key) => key.startsWith("pk_test_") || key.startsWith("pk_live_"),
      "Publishable key must start with pk_test_ or pk_live_",
    ),
  webhookSecret: z.string().optional(),
});

/**
 * GET /api/staff/settings/stripe-keys
 */
export async function GET(request: NextRequest) {
  try {
    const session = await validateStaffSession();
    if (!session) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    if (session.role !== "ADMIN" && session.role !== "SUPER_ADMIN") {
      return NextResponse.json(
        { error: "Admin access required" },
        { status: 403 },
      );
    }

    let organizationId = request.nextUrl.searchParams.get("organizationId");

    if (!organizationId) {
      organizationId = await getStaffOrganizationId(session.email);
    }

    if (!organizationId) {
      return NextResponse.json(
        {
          success: false,
          error: "No organization found",
          message: "Please set up your organization first.",
        },
        { status: 400 },
      );
    }

    // stripeKeysService handles its own storage -- stays as-is
    const keys = await stripeKeysService.getMaskedKeys(organizationId);

    return NextResponse.json({
      success: true,
      organizationId,
      hasKeys: !!keys,
      ...(keys && {
        mode: keys.mode,
        configuredAt: keys.configuredAt,
        maskedSecretKey: keys.secretKeyMasked,
        maskedWebhookSecret: keys.webhookSecretMasked,
        publishableKey: keys.publishableKey,
      }),
    });
  } catch (error) {
    logger.error("Failed to get Stripe keys", { error });
    return NextResponse.json(
      { success: false, error: "Failed to load Stripe keys" },
      { status: 500 },
    );
  }
}

/**
 * POST /api/staff/settings/stripe-keys
 */
export async function POST(request: NextRequest) {
  try {
    const session = await validateStaffSession();
    if (!session) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    if (session.role !== "ADMIN" && session.role !== "SUPER_ADMIN") {
      return NextResponse.json(
        { error: "Admin access required" },
        { status: 403 },
      );
    }

    const body = await request.json();
    const validationResult = saveKeysSchema.safeParse(body);

    if (!validationResult.success) {
      return NextResponse.json(
        {
          success: false,
          error: "Invalid request: " + validationResult.error.errors[0].message,
        },
        { status: 400 },
      );
    }

    const { secretKey, publishableKey, webhookSecret } = validationResult.data;

    let organizationId = validationResult.data.organizationId;
    if (!organizationId) {
      organizationId = await getStaffOrganizationId(session.email);
    }

    if (!organizationId) {
      return NextResponse.json(
        {
          success: false,
          error: "No organization found",
          message: "Please set up your organization first.",
        },
        { status: 400 },
      );
    }

    const secretMode = secretKey.startsWith("sk_test_") ? "test" : "live";
    const publishableMode = publishableKey.startsWith("pk_test_")
      ? "test"
      : "live";

    if (secretMode !== publishableMode) {
      return NextResponse.json(
        {
          success: false,
          error:
            "Key mode mismatch: secret key and publishable key must both be test or both be live",
        },
        { status: 400 },
      );
    }

    // Stripe API validation stays as-is
    const validation = await stripeKeysService.validateKeys(
      secretKey,
      publishableKey,
    );

    if (!validation.valid) {
      return NextResponse.json(
        { success: false, error: validation.error || "Invalid Stripe keys" },
        { status: 400 },
      );
    }

    const success = await stripeKeysService.saveKeys(
      organizationId,
      { secretKey, publishableKey, webhookSecret },
      session.id,
    );

    if (!success) {
      return NextResponse.json(
        { success: false, error: "Failed to save Stripe keys" },
        { status: 500 },
      );
    }

    logger.info("Stripe keys saved by staff", {
      organizationId,
      staffId: session.id,
      staffRole: session.role,
      mode: validation.mode,
      accountName: validation.accountName,
    });

    return NextResponse.json({
      success: true,
      message: `Stripe keys saved successfully (${validation.mode} mode)`,
      mode: validation.mode,
      accountName: validation.accountName,
    });
  } catch (error) {
    logger.error("Failed to save Stripe keys", { error });
    return NextResponse.json(
      { success: false, error: "Failed to save Stripe keys" },
      { status: 500 },
    );
  }
}

/**
 * DELETE /api/staff/settings/stripe-keys
 */
export async function DELETE(request: NextRequest) {
  try {
    const session = await validateStaffSession();
    if (!session) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    if (session.role !== "SUPER_ADMIN") {
      return NextResponse.json(
        { error: "Super admin access required for deletion" },
        { status: 403 },
      );
    }

    let organizationId = request.nextUrl.searchParams.get("organizationId");

    if (!organizationId) {
      organizationId = await getStaffOrganizationId(session.email);
    }

    if (!organizationId) {
      return NextResponse.json(
        {
          success: false,
          error: "No organization found",
          message: "Please set up your organization first.",
        },
        { status: 400 },
      );
    }

    const success = await stripeKeysService.deleteKeys(
      organizationId,
      session.id,
    );

    if (!success) {
      return NextResponse.json(
        { success: false, error: "Failed to delete Stripe keys" },
        { status: 500 },
      );
    }

    logger.info("Stripe keys deleted by staff", {
      organizationId,
      staffId: session.id,
    });

    return NextResponse.json({
      success: true,
      message: "Stripe keys deleted successfully",
    });
  } catch (error) {
    logger.error("Failed to delete Stripe keys", { error });
    return NextResponse.json(
      { success: false, error: "Failed to delete Stripe keys" },
      { status: 500 },
    );
  }
}
