import { headers } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';
import { verifySigningToken } from '@/lib/signing/token';
import { logAuditEvent } from '@/lib/signing/audit';
import { db } from '@/lib/db';
import { signingTokens, documents } from '@/lib/db/schema';
import { eq } from 'drizzle-orm';

// Public route — no auth session required
export async function GET(
  _req: NextRequest,
  { params }: { params: Promise<{ token: string }> }
) {
  const { token } = await params;

  // Extract IP and user-agent for audit logging
  const hdrs = await headers();
  const ip =
    hdrs.get('x-forwarded-for')?.split(',')[0]?.trim() ??
    hdrs.get('x-real-ip') ??
    'unknown';
  const ua = hdrs.get('user-agent') ?? 'unknown';

  // 1. Verify JWT
  let payload: { documentId: string; jti: string; exp: number };
  try {
    payload = await verifySigningToken(token);
  } catch (err: unknown) {
    // Check if it's a JWT expiry error
    const errName = err instanceof Error ? err.constructor.name : '';
    const errMessage = err instanceof Error ? err.message : '';
    if (errName === 'JWTExpired' || errMessage.includes('expired')) {
      return NextResponse.json({ status: 'expired' }, { status: 200 });
    }
    return NextResponse.json({ status: 'invalid' }, { status: 200 });
  }

  // 2. Look up jti in signingTokens table
  const tokenRow = await db.query.signingTokens.findFirst({
    where: eq(signingTokens.jti, payload.jti),
  });

  if (!tokenRow) {
    return NextResponse.json({ status: 'invalid' }, { status: 200 });
  }

  // 3. Check one-time use
  if (tokenRow.usedAt !== null) {
    return NextResponse.json(
      { status: 'used', signedAt: tokenRow.usedAt.toISOString() },
      { status: 200 }
    );
  }

  // 4. Fetch document
  const doc = await db.query.documents.findFirst({
    where: eq(documents.id, payload.documentId),
    columns: {
      id: true,
      name: true,
      signatureFields: true,
      preparedFilePath: true,
    },
  });

  if (!doc || !doc.preparedFilePath) {
    return NextResponse.json({ status: 'invalid' }, { status: 200 });
  }

  // 5 & 6. Log audit events: link_opened + document_viewed
  await logAuditEvent({
    documentId: payload.documentId,
    eventType: 'link_opened',
    ipAddress: ip,
    userAgent: ua,
  });

  await logAuditEvent({
    documentId: payload.documentId,
    eventType: 'document_viewed',
    ipAddress: ip,
    userAgent: ua,
  });

  // 7. Return pending state with document data
  return NextResponse.json({
    status: 'pending',
    document: {
      id: doc.id,
      name: doc.name,
      signatureFields: doc.signatureFields ?? [],
      preparedFilePath: doc.preparedFilePath,
    },
    expiresAt: new Date(payload.exp * 1000).toISOString(),
  });
}
