import { publicProcedure } from './router';
import { z } from 'zod';
import { eq, sql } from 'drizzle-orm';
import { waitlistSignups, waitlistEvents } from '../../src/db/schema';

function generateReferralCode(length = 8): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let code = '';
  for (let i = 0; i < length; i++) {
    code += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return code;
}

export const waitlistRouter = {
  signup: publicProcedure
    .input(z.object({
      email: z.string().email(),
      name: z.string().min(1).max(200).optional(),
      source: z.string().max(100).optional().default('organic'),
      referralCode: z.string().max(20).optional(),
    }))
    .mutation(async ({ input, ctx }) => {
      const existingRows = await ctx.db!.select()
        .from(waitlistSignups)
        .where(eq(waitlistSignups.email, input.email.toLowerCase()));
      const existing = existingRows[0];

      if (existing) {
        const metaStr = (existing as Record<string, unknown>).metadata as string | null;
        const existingMeta = metaStr ? JSON.parse(metaStr) : {};
        return { success: true, alreadyJoined: true, id: existing.id, referralCode: existingMeta.referralCode || null };
      }

      const metadata: Record<string, unknown> = {};
      if (input.referralCode) {
        metadata.referredBy = input.referralCode;
      }
      metadata.referralCode = generateReferralCode();

      const result = await ctx.db!.insert(waitlistSignups)
        .values({
          email: input.email.toLowerCase(),
          name: input.name ?? null,
          source: input.source ?? 'organic',
          metadata: JSON.stringify(metadata),
        })
        .returning();

      const signup = result[0];

      await ctx.db!.insert(waitlistEvents)
        .values({
          signupId: signup!.id,
          eventType: 'signup',
          eventData: JSON.stringify({ source: input.source, referralCode: input.referralCode }),
        });

      const referralCode = metadata.referralCode as string;
      return { success: true, alreadyJoined: false, id: signup!.id, referralCode };
    }),

  getCount: publicProcedure
    .query(async ({ ctx }) => {
      const result = await ctx.db!.select({ count: sql<number>`count(*)` })
        .from(waitlistSignups)
        .where(eq(waitlistSignups.status, 'waitlist'));
      return { count: Number(result[0]!.count) };
    }),

  getReferralCount: publicProcedure
    .input(z.object({ referralCode: z.string().min(1).max(20) }))
    .query(async ({ input, ctx }) => {
      const rows = await ctx.db!.select({ id: waitlistSignups.id })
        .from(waitlistSignups)
        .where(eq(waitlistSignups.status, 'waitlist'));

      let count = 0;
      for (const row of rows) {
        const metaStr = (row as Record<string, unknown>).metadata as string | null;
        const meta = metaStr ? JSON.parse(metaStr) : {};
        if (meta.referredBy === input.referralCode) {
          count++;
        }
      }
      return { count };
    }),
};
