import { redirect } from "next/navigation";
import { currentUser } from "@clerk/nextjs/server";
import { convexQuery, convexMutation } from "@/lib/convex-client";
import { CONVEX_PATHS } from "@/lib/convex-paths";
import { type Lang } from "@/lib/config";
import { prisma } from "@/lib/db";
import { logger } from "@/lib/logger";

interface ConvexUser {
  _id: string;
  email: string;
  name: string;
  clerkId?: string;
  onboardingComplete: boolean;
}

// Force dynamic rendering — reads Clerk auth on every request
export const dynamic = "force-dynamic";

export default async function OnboardingPage({
  params,
}: {
  params: { lang: Lang };
}) {
  const { lang } = params;

  // 1. Get current Clerk user
  const clerkUser = await currentUser();
  if (!clerkUser) {
    redirect(`/${lang}/clerk-login`);
  }

  const email = clerkUser.emailAddresses[0]?.emailAddress?.toLowerCase();
  if (!email) {
    redirect(`/${lang}/clerk-login`);
  }

  const name =
    [clerkUser.firstName, clerkUser.lastName].filter(Boolean).join(" ") ||
    email.split("@")[0];

  // 2. PRISMA FIRST — always create/upsert the Postgres user before anything else.
  // This guarantees downstream routes (company-info, checkout) can find the user,
  // regardless of whether Convex succeeds or fails.
  let prismaUserId: string | undefined;
  let prismaOnboardingComplete = false;
  let hasActiveSubscription = false;
  let hasRequiredOnboardingInfo = false;
  try {
    const prismaUser = await prisma.users.upsert({
      where: { email },
      update: { name, updatedAt: new Date() },
      create: {
        id: crypto.randomUUID(),
        email,
        name,
        updatedAt: new Date(),
        onboardingComplete: false,
      },
      select: {
        id: true,
        onboardingComplete: true,
        companyName: true,
        companySize: true,
        industry: true,
        country: true,
        subscriptions: {
          where: {
            status: { in: ["active", "trialing"] },
            currentPeriodEnd: { gt: new Date() },
          },
          select: { id: true },
          take: 1,
        },
      },
    });
    prismaUserId = prismaUser.id;
    prismaOnboardingComplete = prismaUser.onboardingComplete;
    hasActiveSubscription = prismaUser.subscriptions.length > 0;
    hasRequiredOnboardingInfo =
      !!prismaUser.companyName?.trim() &&
      !!prismaUser.industry?.trim() &&
      !!prismaUser.companySize?.trim() &&
      !!prismaUser.country?.trim();

    logger.info("Prisma user ensured for onboarding", {
      prismaUserId,
      email,
      prismaOnboardingComplete,
      hasActiveSubscription,
      hasRequiredOnboardingInfo,
    });
  } catch (prismaErr) {
    logger.error("Prisma upsert failed during onboarding", {
      error: prismaErr,
      email,
    });
    // Continue — try Convex path, but user may hit issues downstream
  }

  // 3. Initialize Convex user + organization (public mutation — works with ConvexHttpClient)
  let convexUser: ConvexUser | null = null;
  try {
    convexUser = (await convexQuery(CONVEX_PATHS.getUserByEmail, {
      email,
    })) as ConvexUser | null;

    if (!convexUser) {
      // initializeClerkUser is a public mutation that creates user + org + membership atomically
      const newId = await convexMutation(CONVEX_PATHS.initializeClerkUser, {
        email,
        name,
        clerkId: clerkUser.id,
        prismaId: prismaUserId,
      });

      if (newId) {
        convexUser = (await convexQuery(CONVEX_PATHS.getUserByEmail, {
          email,
        })) as ConvexUser | null;
      }
    } else if (!convexUser.clerkId && clerkUser.id) {
      // Existing user but missing clerkId — re-run initialize to link + ensure org exists
      await convexMutation(CONVEX_PATHS.initializeClerkUser, {
        email,
        name,
        clerkId: clerkUser.id,
        prismaId: prismaUserId,
      }).catch(() => {
        /* non-fatal backfill */
      });
    }
  } catch (convexErr) {
    logger.warn("Convex user initialization failed (non-fatal)", {
      error: convexErr,
      email,
    });
    // Continue — Prisma is sufficient for the onboarding flow
  }

  // 4. Determine if new user needs onboarding
  // Check BOTH Prisma AND Convex — either is authoritative for completion status.
  // Users are considered fully onboarded only when required company fields are saved.
  const hasCompletionSignal =
    prismaOnboardingComplete ||
    hasActiveSubscription ||
    convexUser?.onboardingComplete === true;
  const isOnboardingComplete = hasCompletionSignal && hasRequiredOnboardingInfo;

  // Backfill Prisma if Convex is ahead (prevents future redirect loops)
  if (
    convexUser?.onboardingComplete &&
    !prismaOnboardingComplete &&
    prismaUserId
  ) {
    prisma.users
      .update({
        where: { id: prismaUserId },
        data: { onboardingComplete: true },
      })
      .catch((err) =>
        logger.warn("Backfill onboardingComplete failed", { err }),
      );
  }

  if (!isOnboardingComplete) {
    // Prisma ID is preferred (needed by Stripe webhook to link subscriptions)
    // Fall back to Convex ID if Prisma write failed
    const wizardUserId = prismaUserId ?? convexUser?._id ?? "";
    if (!wizardUserId) {
      // Both DB writes failed — cannot proceed, redirect to login
      logger.error("Both Prisma and Convex failed — cannot create user", {
        email,
      });
      redirect(`/${lang}/clerk-login`);
    }
    const skipPaymentQuery = hasActiveSubscription ? "&skipPayment=true" : "";
    redirect(
      `/${lang}/onboarding/setup?userId=${wizardUserId}${skipPaymentQuery}`,
    );
  }

  redirect(`/${lang}/dashboard`);
}
