import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';

import { auth } from '@/lib/auth';
import { errorResponse, NotFoundError } from '@/lib/errors';
import { consumeCrmInvite } from '@/lib/services/crm-invite.service';
import { enforcePublicRateLimit, parseBody } from '@/lib/api/route-helpers';

const bodySchema = z.object({
  token: z.string().min(1),
  password: z.string().min(9),
});

export async function POST(req: NextRequest): Promise<NextResponse> {
  // 10/hour/IP - bounds brute-force against either token store.
  const limited = await enforcePublicRateLimit(req, 'portalToken');
  if (limited) return limited;

  try {
    const { token, password } = await parseBody(req, bodySchema);

    // Two distinct token issuers can land users on /set-password:
    //   1. CRM admin invite → `crm_user_invites` row, consumed via
    //      `consumeCrmInvite` (creates the better-auth user + profile).
    //   2. Forgot-password → better-auth verification row, consumed via
    //      `auth.api.resetPassword` (rotates the password on an existing
    //      user).
    // Try the CRM-invite path first. If the token isn't in that table
    // (NotFoundError), fall through to better-auth - these are mutually
    // exclusive token spaces, so at most one will accept it.
    try {
      const result = await consumeCrmInvite({ token, password });
      return NextResponse.json({ data: { email: result.email } });
    } catch (err) {
      if (!(err instanceof NotFoundError)) throw err;
    }

    try {
      await auth.api.resetPassword({
        body: { newPassword: password, token },
      });
      return NextResponse.json({ data: { email: null } });
    } catch {
      // Both stores rejected the token; surface a clean unified error
      // (matches the `{ error: string }` shape the page consumes via
      // `body.error`).
      return NextResponse.json(
        {
          error: 'This link is invalid or has expired. Request a new one.',
          code: 'INVITE_OR_RESET_INVALID',
        },
        { status: 400 },
      );
    }
  } catch (err) {
    return errorResponse(err);
  }
}
