/**
 * Public one-click unsubscribe endpoint.
 *
 * GET   → browser confirmation page (sets opt_out and shows HTML).
 * POST  → RFC 8058 List-Unsubscribe-Post handler used by Gmail/Apple Mail
 *         when the user clicks the inline "Unsubscribe" button. Returns
 *         a 204 with no body — the user never sees this response.
 *
 * No session required. All authority comes from the HMAC-signed token.
 */

import { NextRequest, NextResponse } from 'next/server';
import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';
import { initDatabase } from '@server/db/init';
import { verifyUnsubscribeToken } from '@server/services/marketing/unsubscribe-token';

import { childLogger } from '@server/logger';
import { wrapRouteHandler } from '@server/logger/request';
const log = childLogger('route.public.unsubscribe.token');

interface RouteContext { params: Promise<{ token: string }> }

async function applyOptOut(restaurantId: string, customerId: string, reason: string): Promise<void> {
  await initDatabase();
  await db.execute(sql`
    UPDATE customers
    SET marketing_opt_out = true,
        opt_out_at = COALESCE(opt_out_at, now()),
        opt_out_reason = COALESCE(opt_out_reason, ${reason})
    WHERE id = ${customerId} AND restaurant_id = ${restaurantId}
  `);
}

function htmlPage(title: string, message: string): string {
  return `<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>${title}</title>
  <style>
    body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:#f9fafb;margin:0;padding:48px 16px;color:#111827}
    .card{max-width:480px;margin:0 auto;background:white;border-radius:12px;padding:32px;box-shadow:0 1px 3px rgba(0,0,0,.08);text-align:center}
    h1{font-size:20px;margin:0 0 12px}
    p{font-size:14px;color:#4b5563;line-height:1.5;margin:8px 0}
  </style>
</head><body>
  <div class="card">
    <h1>${title}</h1>
    <p>${message}</p>
  </div>
</body></html>`;
}

async function handleGET(_req: NextRequest, ctx: RouteContext): Promise<NextResponse> {
  const { token } = await ctx.params;
  const payload = verifyUnsubscribeToken(token);
  if (!payload) {
    return new NextResponse(
      htmlPage('Link expired', 'This unsubscribe link is invalid or has expired. Please reply STOP to any message to opt out.'),
      { status: 400, headers: { 'Content-Type': 'text/html; charset=utf-8' } },
    );
  }
  try {
    await applyOptOut(payload.restaurantId, payload.customerId, 'email link');
    return new NextResponse(
      htmlPage('You have been unsubscribed', 'You will no longer receive marketing emails from this restaurant. You may still receive transactional messages about your orders or bookings.'),
      { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } },
    );
  } catch (err) {
    log.error({ err }, 'unsubscribe GET failed');
    return new NextResponse(
      htmlPage('Something went wrong', 'We could not process your request right now. Please try again later or reply STOP to opt out by message.'),
      { status: 500, headers: { 'Content-Type': 'text/html; charset=utf-8' } },
    );
  }
}

async function handlePOST(_req: NextRequest, ctx: RouteContext): Promise<NextResponse> {
  const { token } = await ctx.params;
  const payload = verifyUnsubscribeToken(token);
  if (!payload) return new NextResponse(null, { status: 400 });
  try {
    await applyOptOut(payload.restaurantId, payload.customerId, 'email one-click');
  } catch (err) {
    log.error({ err }, 'unsubscribe POST failed');
    return new NextResponse(null, { status: 500 });
  }
  return new NextResponse(null, { status: 204 });
}

export const GET = wrapRouteHandler((req: Request, ctx: unknown) => handleGET(req as NextRequest, ctx as RouteContext));
export const POST = wrapRouteHandler((req: Request, ctx: unknown) => handlePOST(req as NextRequest, ctx as RouteContext));
