'use server';

import { cookies, headers } from 'next/headers';
import { hashPassword, createSession } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { getInstanceSettings } from '@/lib/instanceSettings';
import { ensureLibraryForUser } from '@/lib/library';
import { rateLimit, clientIpFromHeaders } from '@/lib/rateLimit';

const EMAIL_RE = /^[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$/;

export async function signupAction(
  email: string,
  password: string,
  passwordConfirm: string,
  name?: string,
) {
  try {
    // Per-IP cap: 5 sign-ups per 15 minutes. Generous enough for
    // legitimate use (testing, household members coming online together)
    // but cuts off automated account spraying.
    const hdrs = await headers();
    const ip = clientIpFromHeaders(hdrs);
    const limit = rateLimit(`signup:${ip}`, { limit: 5, windowMs: 15 * 60_000 });
    if (!limit.ok) {
      return {
        error: `Too many sign-up attempts. Try again in ${limit.retryAfterSec}s.`,
      };
    }

    const settings = await getInstanceSettings();
    if (!settings.signupsOpen) {
      return { error: 'New sign-ups are not enabled on this instance.' };
    }

    if (!EMAIL_RE.test(email)) {
      return { error: 'Enter a valid email address.' };
    }
    if (password.length < 8) {
      return { error: 'Password must be at least 8 characters.' };
    }
    if (password !== passwordConfirm) {
      return { error: 'Passwords do not match.' };
    }

    const existing = await prisma.user.findUnique({ where: { email } });
    if (existing) {
      // Don't leak existence — generic message keeps probing harder.
      return { error: 'Could not create account with that email.' };
    }

    const passwordHash = await hashPassword(password);

    const user = await prisma.user.create({
      data: {
        email,
        passwordHash,
        name: name?.trim() || null,
        isAdmin: false,
        userPreferences: {
          create: {
            theme: 'system',
            defaultWeightUnit: 'lbs',
            defaultRestSeconds: 90,
          },
        },
      },
    });

    // Seed the curated exercise library for the new user immediately so they
    // see exercises on first load. The boot-time ensure step would do this
    // on next restart anyway, but we don't want them to wait.
    await ensureLibraryForUser(user.id);

    const session = await createSession(user.id);
    const cookieStore = await cookies();
    cookieStore.set('sessionToken', session.token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      maxAge: 60 * 60 * 24 * 30,
      path: '/',
    });

    return { success: true };
  } catch (error) {
    console.error('Signup error:', error);
    return { error: 'An error occurred during sign-up.' };
  }
}

export async function getSignupsOpen(): Promise<boolean> {
  const settings = await getInstanceSettings();
  return settings.signupsOpen;
}
