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

import { withAuth, withPermission } from '@/lib/api/helpers';
import { errorResponse } from '@/lib/errors';
import {
  getTokenForResend,
  issueToken,
  listTokensForInterest,
} from '@/lib/services/supplemental-forms.service';
import { sendEmail } from '@/lib/email';
import { env } from '@/lib/env';
import { getPortBrandingConfig, getPortEmailConfig } from '@/lib/services/port-config';
import { brandingPrimaryColor, renderShell } from '@/lib/email/shell';

/**
 * POST /api/v1/interests/[id]/supplemental-info-request
 *
 * Auth: requires `interests.edit` so any rep working the deal can fire it.
 * Generates a one-shot token + emails the client the public form URL.
 */
/**
 * GET - list past issuances for the interest. Lets the rep see when each
 * token was generated + which one is currently active, so they can choose
 * Resend (re-email the existing token) over Regenerate (mint a fresh one)
 * when the same client is still working through the existing form.
 */
export const GET = withAuth(
  withPermission('interests', 'view', async (_req, ctx, params) => {
    try {
      const rows = await listTokensForInterest(ctx.portId, params.id!);
      return NextResponse.json({ data: rows });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

export const POST = withAuth(
  withPermission('interests', 'edit', async (req: NextRequest, ctx, params) => {
    try {
      const interestId = params.id as string;
      // Three flows surface here today:
      //   1. New token + email (default).
      //   2. New token, no email (rep copies + shares manually).
      //   3. Resend an existing token via email (no new token minted).
      // `tokenId` in the body opts into (3); otherwise (1)/(2) apply
      // based on `sendEmail`. Older callers POST with no body and still
      // trigger (1).
      let shouldSendEmail = true;
      let resendTokenId: string | null = null;
      try {
        const body = (await req.clone().json()) as {
          sendEmail?: boolean;
          tokenId?: string;
        };
        if (typeof body?.sendEmail === 'boolean') shouldSendEmail = body.sendEmail;
        if (typeof body?.tokenId === 'string' && body.tokenId.length > 0) {
          resendTokenId = body.tokenId;
        }
      } catch {
        // No JSON body - keep the default.
      }

      const result = resendTokenId
        ? await getTokenForResend(ctx.portId, interestId, resendTokenId)
        : await issueToken({
            interestId,
            portId: ctx.portId,
            issuedBy: ctx.userId,
          });

      // §1.4: prefer the per-port supplemental_form_url (typically the
      // marketing site's hosted form) when configured; otherwise fall
      // back to the built-in CRM route. Both modes use the same token
      // - the marketing site forwards the token to the same backend.
      const emailCfg = await getPortEmailConfig(ctx.portId);
      const link = emailCfg.supplementalFormUrl
        ? `${emailCfg.supplementalFormUrl}?token=${encodeURIComponent(result.token)}`
        : `${env.NEXT_PUBLIC_APP_URL}/public/supplemental-info/${result.token}`;

      // Resend implies "email me again" - the rep clicked the action with
      // intent. Force the email path on for resends regardless of the
      // `sendEmail` body flag.
      const willSendEmail = resendTokenId ? true : shouldSendEmail;
      if (willSendEmail && result.clientEmail) {
        // Render through the shared branded shell (logo + blurred overhead
        // background + max-width 600 table layout) so the supplemental-
        // info email matches portal-activation / reset / login + the rest
        // of the branded surfaces. Per-port branding (logo, primary
        // color, background image, header/footer) flows from
        // system_settings via getPortBrandingConfig.
        const branding = await getPortBrandingConfig(ctx.portId);
        const accent = brandingPrimaryColor({
          logoUrl: branding.logoUrl,
          backgroundUrl: branding.emailBackgroundUrl,
          primaryColor: branding.primaryColor,
          emailHeaderHtml: branding.emailHeaderHtml,
          emailFooterHtml: branding.emailFooterHtml,
        });
        const body = `
          <h1 style="font-family:Arial,sans-serif;font-size:20px;font-weight:600;color:#0f172a;margin:0 0 16px;">
            One quick step before your EOI
          </h1>
          <p style="font-family:Arial,sans-serif;font-size:14px;line-height:1.55;color:#334155;margin:0 0 12px;">
            Hello ${escapeHtml(result.clientName)},
          </p>
          <p style="font-family:Arial,sans-serif;font-size:14px;line-height:1.55;color:#334155;margin:0 0 16px;">
            Before we draft your Expression of Interest, we need to confirm a few details.
            The form below is pre-filled with what we have on file - please review, correct
            anything that&apos;s wrong, and add what&apos;s missing.
          </p>
          <p style="text-align:center;margin:24px 0;">
            <a href="${link}"
               style="display:inline-block;background:${accent};color:#ffffff;text-decoration:none;padding:12px 24px;border-radius:6px;font-family:Arial,sans-serif;font-size:14px;font-weight:600;">
              Open the form
            </a>
          </p>
          <p style="font-family:Arial,sans-serif;font-size:12px;color:#64748b;margin:0 0 4px;">
            This link expires on ${result.expiresAt.toUTCString()}.
          </p>
          <p style="font-family:Arial,sans-serif;font-size:12px;color:#64748b;margin:0;">
            If you didn&apos;t expect this email, please let us know.
          </p>
        `;
        const html = renderShell({
          title: 'Please complete a few details before we draft your EOI',
          body,
          branding: {
            logoUrl: branding.logoUrl,
            backgroundUrl: branding.emailBackgroundUrl,
            primaryColor: branding.primaryColor,
            emailHeaderHtml: branding.emailHeaderHtml,
            emailFooterHtml: branding.emailFooterHtml,
          },
        });
        await sendEmail(
          result.clientEmail,
          'Please complete a few details before we draft your EOI',
          html,
          undefined,
          undefined,
          ctx.portId,
        );
      }

      return NextResponse.json({
        data: {
          link,
          expiresAt: result.expiresAt.toISOString(),
          emailSent: willSendEmail && !!result.clientEmail,
          resent: !!resendTokenId,
        },
      });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

function escapeHtml(s: string): string {
  return s
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}
