import { createServerFn } from "@tanstack/react-start";
import { eq } from "drizzle-orm";
import { z } from "zod";
import { user, userOnboardingAnswers } from "@/db/schema";
import { db } from "@/db";
import { requireAuthenticatedContext } from "@/serverFunctions/middleware";

const onboardingAnswersSchema = z.object({
  interestedFeatures: z.array(z.string()).optional(),
  workFor: z.string().optional(),
  clientWebsiteCount: z.string().optional(),
  foundVia: z.string().optional(),
  mcpSetupIntent: z.enum(["yes", "no"]).optional(),
  completed: z.boolean().optional(),
});

export const getOnboardingAnswers = createServerFn({ method: "GET" })
  .middleware(requireAuthenticatedContext)
  .handler(async ({ context }) => {
    const answers = await db.query.userOnboardingAnswers.findFirst({
      columns: {
        completedAt: true,
        gscNudgeDismissedAt: true,
        interestedFeatures: true,
        workFor: true,
        clientWebsiteCount: true,
        foundVia: true,
        mcpSetupIntent: true,
      },
      where: eq(userOnboardingAnswers.userId, context.userId),
    });
    const userRecord = await db.query.user.findFirst({
      columns: {
        createdAt: true,
      },
      where: eq(user.id, context.userId),
    });

    let interestedFeatures: string[] = [];
    if (answers?.interestedFeatures) {
      try {
        const parsed: unknown = JSON.parse(answers.interestedFeatures);
        if (Array.isArray(parsed)) {
          interestedFeatures = parsed.filter(
            (value): value is string => typeof value === "string",
          );
        }
      } catch {
        interestedFeatures = [];
      }
    }

    return {
      completedAt: answers?.completedAt ?? null,
      gscNudgeDismissedAt: answers?.gscNudgeDismissedAt ?? null,
      userCreatedAt: userRecord?.createdAt?.toISOString() ?? null,
      answers: {
        interestedFeatures,
        workFor: answers?.workFor ?? null,
        clientWebsiteCount: answers?.clientWebsiteCount ?? null,
        foundVia: answers?.foundVia ?? null,
        mcpSetupIntent: answers?.mcpSetupIntent ?? null,
      },
    };
  });

export const saveOnboardingAnswers = createServerFn({ method: "POST" })
  .middleware(requireAuthenticatedContext)
  .inputValidator((data: unknown) => onboardingAnswersSchema.parse(data))
  .handler(async ({ data, context }) => {
    const now = new Date().toISOString();
    const completedAt = data.completed ? now : undefined;
    const set = {
      ...(data.interestedFeatures
        ? { interestedFeatures: JSON.stringify(data.interestedFeatures) }
        : {}),
      ...(data.workFor !== undefined ? { workFor: data.workFor } : {}),
      ...(data.clientWebsiteCount !== undefined
        ? { clientWebsiteCount: data.clientWebsiteCount }
        : {}),
      ...(data.foundVia !== undefined ? { foundVia: data.foundVia } : {}),
      ...(data.mcpSetupIntent !== undefined
        ? { mcpSetupIntent: data.mcpSetupIntent }
        : {}),
      // Completing onboarding means the user passed the Search Console step, so
      // resolve the GSC prompt — the legacy re-engagement nudge must not fire
      // for anyone who already saw that step.
      ...(completedAt !== undefined
        ? { completedAt, gscNudgeDismissedAt: completedAt }
        : {}),
      updatedAt: now,
    };

    await db
      .insert(userOnboardingAnswers)
      .values({
        userId: context.userId,
        organizationId: context.organizationId,
        interestedFeatures: JSON.stringify(data.interestedFeatures ?? []),
        workFor: data.workFor,
        clientWebsiteCount: data.clientWebsiteCount,
        foundVia: data.foundVia,
        mcpSetupIntent: data.mcpSetupIntent,
        completedAt,
        gscNudgeDismissedAt: completedAt,
        updatedAt: now,
      })
      .onConflictDoUpdate({
        target: userOnboardingAnswers.userId,
        set,
      });

    return { ok: true };
  });

// Records that the one-time "connect Search Console" nudge has been shown and
// resolved (dismissed or acted on) so it never reappears for this user.
export const dismissGscNudge = createServerFn({ method: "POST" })
  .middleware(requireAuthenticatedContext)
  .handler(async ({ context }) => {
    const now = new Date().toISOString();
    await db
      .insert(userOnboardingAnswers)
      .values({
        userId: context.userId,
        organizationId: context.organizationId,
        gscNudgeDismissedAt: now,
        updatedAt: now,
      })
      .onConflictDoUpdate({
        target: userOnboardingAnswers.userId,
        set: { gscNudgeDismissedAt: now, updatedAt: now },
      });

    return { ok: true };
  });
