/**
 * Twilio WhatsApp Credentials Dashboard API
 *
 * GET   /api/dashboard/twilio-credentials?organizationId=...
 *   Returns the org's current Twilio WhatsApp credentials in masked form,
 *   plus the public webhook URL the owner needs to paste into the Twilio
 *   console.
 *
 * PATCH /api/dashboard/twilio-credentials
 *   Saves new credentials. Auth token is encrypted with AES-256-GCM
 *   before storage. Body:
 *   {
 *     organizationId: string,
 *     twilioAccountSid: string,
 *     twilioAuthToken: string,        // plaintext — we encrypt
 *     twilioWhatsappNumber: string,   // E.164, no `whatsapp:` prefix
 *   }
 *
 * Auth & ownership:
 *   - Authenticated user only
 *   - User must own the organization
 *   - PATCH requires a valid CSRF token
 */

import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { auth } from "@/lib/auth";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import { validateCSRFToken } from "@/lib/csrf";
import { rateLimiters, applyRateLimit } from "@/lib/rate-limiter";
import { logger } from "@/lib/logger";
import prisma from "@/lib/db";
import { convexMutation } from "@/lib/convex-client";
import { encrypt } from "@/lib/encryption";

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

const patchSchema = z.object({
  organizationId: z.string().min(1, "organizationId is required"),
  twilioAccountSid: z
    .string()
    .min(1, "Account SID is required")
    .regex(/^AC[a-zA-Z0-9]{32}$/, "Account SID must start with AC and be 34 chars"),
  twilioAuthToken: z
    .string()
    .min(32, "Auth token must be at least 32 characters"),
  twilioWhatsappNumber: z
    .string()
    .min(1, "WhatsApp number is required")
    .regex(/^\+[1-9]\d{6,14}$/, "Use E.164 format like +14155238886"),
});

function maskToken(token: string | null | undefined): string {
  if (!token) return "";
  if (token.length <= 8) return "****";
  return `${token.slice(0, 4)}${"*".repeat(8)}${token.slice(-4)}`;
}

function buildWebhookUrl(): string {
  const ngrok = process.env.NGROK_URL?.replace(/\/+$/, "");
  const appUrl = process.env.NEXT_PUBLIC_APP_URL?.replace(/\/+$/, "");
  const base = ngrok || appUrl || "http://localhost:9001";
  return `${base}/api/webhooks/twilio-whatsapp`;
}

// ── GET ─────────────────────────────────────────────────────────────────
export async function GET(request: NextRequest) {
  try {
    const rateLimitResponse = await applyRateLimit(
      request,
      rateLimiters.authGeneral,
    );
    if (rateLimitResponse) return rateLimitResponse;

    const user = await getAuthenticatedUser(request, auth);
    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    const url = new URL(request.url);
    const organizationId = url.searchParams.get("organizationId");
    if (!organizationId) {
      return NextResponse.json(
        { success: false, error: "organizationId is required" },
        { status: 400 },
      );
    }

    const org = (await prisma.organizations.findFirst({
      where: { id: organizationId },
      select: {
        id: true,
        ownerId: true,
        twilioAccountSid: true,
        twilioAuthTokenEncrypted: true,
        twilioWhatsappNumber: true,
        twilioWhatsappConfigured: true,
        twilioWhatsappConfiguredAt: true,
      },
    })) as Record<string, unknown> | null;

    if (!org || org.ownerId !== user.userId) {
      return NextResponse.json(
        { success: false, error: "Forbidden" },
        { status: 403 },
      );
    }

    return NextResponse.json({
      success: true,
      configured: !!org.twilioWhatsappConfigured,
      configuredAt: org.twilioWhatsappConfiguredAt ?? null,
      twilioAccountSid: org.twilioAccountSid ?? "",
      twilioAuthTokenMasked: maskToken(
        org.twilioAuthTokenEncrypted as string | null,
      ),
      twilioWhatsappNumber: org.twilioWhatsappNumber ?? "",
      webhookUrl: buildWebhookUrl(),
    });
  } catch (error) {
    scopedLogger.error("Failed to get Twilio credentials", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}

// ── PATCH ───────────────────────────────────────────────────────────────
export async function PATCH(request: NextRequest) {
  try {
    const rateLimitResponse = await applyRateLimit(
      request,
      rateLimiters.authGeneral,
    );
    if (rateLimitResponse) return rateLimitResponse;

    if (!validateCSRFToken(request)) {
      return NextResponse.json(
        { success: false, error: "Invalid CSRF token" },
        { status: 403 },
      );
    }

    const user = await getAuthenticatedUser(request, auth);
    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    const body = await request.json();
    const parsed = patchSchema.safeParse(body);
    if (!parsed.success) {
      return NextResponse.json(
        { success: false, error: parsed.error.errors[0].message },
        { status: 400 },
      );
    }

    const {
      organizationId,
      twilioAccountSid,
      twilioAuthToken,
      twilioWhatsappNumber,
    } = parsed.data;

    // Verify org ownership
    const org = (await prisma.organizations.findFirst({
      where: { id: organizationId },
      select: { id: true, ownerId: true },
    })) as { id: string; ownerId: string } | null;

    if (!org || org.ownerId !== user.userId) {
      return NextResponse.json(
        { success: false, error: "Forbidden" },
        { status: 403 },
      );
    }

    // Encrypt auth token, then persist via the existing
    // updateOrganizationNoAuth Convex mutation (which already accepts
    // all Twilio fields after the recent extension).
    await convexMutation(
      "organizations/mutations:updateOrganizationNoAuth",
      {
        organizationId,
        twilioAccountSid,
        twilioAuthTokenEncrypted: encrypt(twilioAuthToken),
        twilioWhatsappNumber,
        twilioWhatsappConfigured: true,
        twilioWhatsappConfiguredAt: Date.now(),
        twilioWhatsappConfiguredBy: user.userId,
      },
    );

    // Invalidate router cache so the next inbound message picks up
    // the new credentials immediately.
    try {
      const { whatsAppRouter } = await import(
        "@/lib/services/whatsapp-router.service"
      );
      await whatsAppRouter.invalidateOrgCache(organizationId);
    } catch (cacheErr) {
      scopedLogger.warn("Cache invalidation failed (non-fatal)", { cacheErr });
    }

    scopedLogger.info("Twilio credentials saved", {
      organizationId,
      userId: user.userId,
      twilioWhatsappNumber,
    });

    return NextResponse.json({
      success: true,
      webhookUrl: buildWebhookUrl(),
    });
  } catch (error) {
    scopedLogger.error("Failed to save Twilio credentials", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}
