import { Webhook } from "svix";
import type { Route } from "./+types/clerk";
import { findOrCreateUser, getUserDisplayName } from "~/models/user";
import { logger } from "~/lib/logger";

export async function action({ request }: Route.ActionArgs) {
  // Get the webhook secret from environment
  const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET;

  if (!WEBHOOK_SECRET) {
    throw new Error("Please add CLERK_WEBHOOK_SECRET to your .env file");
  }

  // Get the headers
  const svix_id = request.headers.get("svix-id");
  const svix_timestamp = request.headers.get("svix-timestamp");
  const svix_signature = request.headers.get("svix-signature");

  // If there are no headers, error out
  if (!svix_id || !svix_timestamp || !svix_signature) {
    return new Response("Error: Missing svix headers", { status: 400 });
  }

  // Get the body
  const payload = await request.text();

  // Create a new Svix instance with your webhook secret
  const wh = new Webhook(WEBHOOK_SECRET);

  let evt: { type: string; data: { id: string; email_addresses?: Array<{ email_address: string }>; username?: string; first_name?: string; last_name?: string; image_url?: string } };

  // Verify the webhook
  try {
    evt = wh.verify(payload, {
      "svix-id": svix_id,
      "svix-timestamp": svix_timestamp,
      "svix-signature": svix_signature,
    }) as typeof evt;
  } catch (err) {
    logger.error("Error verifying webhook:", err);
    return new Response("Error: Verification failed", { status: 400 });
  }

  // Handle the webhook
  const eventType = evt.type;
  logger.log(`Webhook received: ${eventType}`);

  if (eventType === "user.created" || eventType === "user.updated") {
    const { id, email_addresses, username, first_name, last_name, image_url } = evt.data;

    try {
      if (eventType === "user.created") {
        // Create new user
        const user = await findOrCreateUser({
          id,
          emailAddresses:
            email_addresses?.map((e: { email_address: string }) => ({
              emailAddress: e.email_address,
            })) || [],
          username,
          firstName: first_name,
          lastName: last_name,
          imageUrl: image_url,
        });
        logger.log(
          `User created in database: ${user.id} (${getUserDisplayName(user)})`
        );
      } else {
        // Update existing user (or create if doesn't exist)
        const user = await findOrCreateUser({
          id,
          emailAddresses:
            email_addresses?.map((e: { email_address: string }) => ({
              emailAddress: e.email_address,
            })) || [],
          username,
          firstName: first_name,
          lastName: last_name,
          imageUrl: image_url,
        });
        logger.log(
          `User updated in database: ${user.id} (${getUserDisplayName(user)})`
        );
      }
    } catch (error) {
      logger.error(`Error handling ${eventType}:`, error);
      return new Response(
        `Error: Failed to ${eventType === "user.created" ? "create" : "update"} user`,
        {
          status: 500,
        }
      );
    }
  }

  return new Response("Webhook processed successfully", { status: 200 });
}
