/**
 * Organization Stripe Keys API
 *
 * GET /api/settings/stripe-keys - Get masked keys for current user's organization
 * POST /api/settings/stripe-keys - Save Stripe keys for current user's organization
 * DELETE /api/settings/stripe-keys - Delete Stripe keys for current user's organization
 *
 * Only accessible to organization owners/admins (authenticated users).
 * This is for B2B customers to configure their own Stripe keys, not Mawidi staff.
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { stripeKeysService } from "@/lib/services/stripe-keys.service";
import { prisma } from "@/lib/db";
import { logger } from "@/lib/logger";
import { z } from "zod";

/**
 * Helper to get organization ID for current user
 * User must be the owner of an organization or have OWNER/ADMIN role
 */
async function getUserOrganization(userId: string): Promise<{
  organizationId: string | null;
  canManageStripe: boolean;
  role: string | null;
}> {
  // Check if user owns an organization
  const ownedOrg = await prisma.organizations.findUnique({
    where: { ownerId: userId },
    select: { id: true },
  });

  if (ownedOrg) {
    return {
      organizationId: ownedOrg.id,
      canManageStripe: true,
      role: "OWNER",
    };
  }

  // Check if user is an admin member of an organization
  const membership = await prisma.organization_members.findFirst({
    where: {
      userId,
      role: { in: ["OWNER", "ADMIN"] },
    },
    select: {
      organizationId: true,
      role: true,
    },
  });

  if (membership) {
    return {
      organizationId: membership.organizationId,
      canManageStripe: true,
      role: membership.role,
    };
  }

  // User is a staff member - cannot manage Stripe keys
  const staffMembership = await prisma.organization_members.findFirst({
    where: { userId },
    select: {
      organizationId: true,
      role: true,
    },
  });

  if (staffMembership) {
    return {
      organizationId: staffMembership.organizationId,
      canManageStripe: false,
      role: staffMembership.role,
    };
  }

  return { organizationId: null, canManageStripe: false, role: null };
}

// Validation schemas
const saveKeysSchema = z.object({
  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/settings/stripe-keys
 * Get masked Stripe keys for current user's organization
 */
export async function GET() {
  try {
    // Authenticate user
    const session = await auth();
    if (!session?.user?.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Get user's organization
    const { organizationId, canManageStripe, role } = await getUserOrganization(
      session.user.id,
    );

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

    // Get masked keys (anyone in org can view, but only owner/admin can modify)
    const keys = await stripeKeysService.getMaskedKeys(organizationId);

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

/**
 * POST /api/settings/stripe-keys
 * Save Stripe keys for current user's organization
 */
export async function POST(request: NextRequest) {
  try {
    // Authenticate user
    const session = await auth();
    if (!session?.user?.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Get user's organization and check permissions
    const { organizationId, canManageStripe, role } = await getUserOrganization(
      session.user.id,
    );

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

    if (!canManageStripe) {
      return NextResponse.json(
        {
          success: false,
          error: "Permission denied",
          message:
            "Only organization owners and admins can configure payment settings.",
        },
        { 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;

    // Validate that key modes match (test/live)
    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 },
      );
    }

    // Validate keys with Stripe API before saving
    const validation = await stripeKeysService.validateKeys(
      secretKey,
      publishableKey,
    );

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

    // Save keys (using user ID as the "configuredBy" field)
    const success = await stripeKeysService.saveKeys(
      organizationId,
      {
        secretKey,
        publishableKey,
        webhookSecret,
      },
      session.user.id,
    );

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

    logger.info("Stripe keys saved by organization admin", {
      organizationId,
      userId: session.user.id,
      userRole: 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 organization Stripe keys", { error });
    return NextResponse.json(
      { success: false, error: "Failed to save Stripe keys" },
      { status: 500 },
    );
  }
}

/**
 * DELETE /api/settings/stripe-keys
 * Delete Stripe keys for current user's organization
 */
export async function DELETE() {
  try {
    // Authenticate user
    const session = await auth();
    if (!session?.user?.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Get user's organization and check permissions
    const { organizationId, canManageStripe, role } = await getUserOrganization(
      session.user.id,
    );

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

    // Only owner can delete keys (more restrictive than saving)
    if (role !== "OWNER") {
      return NextResponse.json(
        {
          success: false,
          error: "Permission denied",
          message: "Only the organization owner can remove payment settings.",
        },
        { status: 403 },
      );
    }

    // Delete keys
    const success = await stripeKeysService.deleteKeys(
      organizationId,
      session.user.id,
    );

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

    logger.info("Stripe keys deleted by organization owner", {
      organizationId,
      userId: session.user.id,
    });

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