/**
 * POST /api/share/[token]/otp — Requests an OTP for email verification on a share link.
 *
 * Public endpoint — no session required.
 * Body: { email: string }
 * Returns: { ok: true, expires_in: 600 } on success.
 *
 * Rate limiting: One unexpired OTP per (link, email) is enforced — if an
 * unexpired OTP already exists for this email, we return the remaining TTL
 * without generating a new code (prevents OTP flood).
 */

import { verifyShareLink, createOtpForShareLink } from '@/lib/artifact-acl.js';
import { getDb, nowIso } from '@/lib/db.js';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';

export async function POST(req, { params }) {
  try {
    const { token } = await params;

    const body = await req.json().catch(() => ({}));
    const { email } = body || {};

    if (!email || typeof email !== 'string' || !email.includes('@')) {
      return Response.json({ error: 'Valid email is required' }, { status: 400 });
    }

    // Verify the share link is still valid before issuing an OTP.
    const verification = await verifyShareLink(token, req);
    if (!verification.ok) {
      return Response.json(
        { error: verification.reason },
        { status: verification.status || 410 }
      );
    }

    const { link } = verification;

    if (!link.require_email_otp) {
      return Response.json(
        { error: 'This share link does not require email verification' },
        { status: 400 }
      );
    }

    // Prevent OTP flood: check for an unexpired, unverified OTP for this (link, email).
    const db = getDb();

    // P1-3: Lockout bypass prevention — if the most recent OTP for this (link, email)
    // has attempts >= 5 and was created within the last 15 minutes, refuse to issue a
    // new code regardless of expiry. Lockout state is derived from the DB row so it
    // survives server restarts.
    const LOCKOUT_WINDOW_ISO = new Date(Date.now() - 15 * 60 * 1000).toISOString();
    const lockedOut = db
      .prepare(
        `SELECT id, created_at FROM artifact_share_link_otps
         WHERE share_link_id = ? AND email = ?
           AND attempts >= 5
           AND created_at > ?
           AND verified_at IS NULL
         ORDER BY created_at DESC
         LIMIT 1`
      )
      .get(link.id, email.toLowerCase().trim(), LOCKOUT_WINDOW_ISO);

    if (lockedOut) {
      const lockedAt = new Date(lockedOut.created_at).getTime();
      const lockoutEndsAt = lockedAt + 15 * 60 * 1000;
      const retryAfter = Math.max(0, Math.ceil((lockoutEndsAt - Date.now()) / 1000));
      return Response.json(
        { ok: false, reason: 'lockout', retry_after: retryAfter },
        { status: 429 }
      );
    }

    const existing = db
      .prepare(
        `SELECT id, expires_at, attempts FROM artifact_share_link_otps
         WHERE share_link_id = ? AND email = ?
           AND expires_at > ?
           AND verified_at IS NULL
         ORDER BY created_at DESC
         LIMIT 1`
      )
      .get(link.id, email.toLowerCase().trim(), nowIso());

    if (existing && existing.attempts < 5) {
      const remainingMs = new Date(existing.expires_at).getTime() - Date.now();
      const remainingSec = Math.max(0, Math.ceil(remainingMs / 1000));
      // Return success — caller should use the code already sent.
      return Response.json({
        ok: true,
        expires_in: remainingSec,
        message: 'A verification code was already sent to this address. Check your inbox.',
      });
    }

    const normalizedEmail = email.toLowerCase().trim();
    const result = await createOtpForShareLink(link.id, normalizedEmail);

    if (!result.ok) {
      return Response.json({ error: result.error || 'Failed to create OTP' }, { status: 400 });
    }

    return Response.json({
      ok: true,
      expires_in: result.expires_in,
      ...(result.email_sent === false
        ? { warning: 'Verification email could not be sent. Contact the link owner.' }
        : {}),
    });
  } catch (err) {
    if (err?.status) {
      return Response.json({ error: err.error || 'error' }, { status: err.status });
    }
    console.error('POST /api/share/[token]/otp error:', err);
    return Response.json({ error: 'Failed to send verification code' }, { status: 500 });
  }
}
