/**
 * Send a one-off test message to the currently signed-in user. Lets the
 * operator preview rendering and SMTP/WhatsApp wiring without launching
 * the full broadcast.
 */

import { NextResponse } from 'next/server';
import { withErrorHandler, RouteContext } from '@server/middleware/withErrorHandler';
import { withAuth, requireSection, AuthedRequest } from '@server/middleware/withAuth';
import { requirePlanFeature } from '@server/utils/features';
import { getCampaign } from '@server/services/marketing/campaigns.service';
import { effectiveBranchId, loadAccessibleOrThrow } from '@server/utils/branch-access';
import { sendCampaignEmail } from '@server/services/marketing/email-send';
import { sendCampaignWhatsApp } from '@server/services/marketing/whatsapp-send';
import { ValidationError } from '@server/errors';
import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';

export const POST = withErrorHandler(
  withAuth(async (req: AuthedRequest, ctx: RouteContext) => {
    const restaurantId = req.session.restaurantId!;
    await requireSection(req, 'marketing', 'create');
    await requirePlanFeature(restaurantId, 'marketing');
    const { id } = await ctx.params;
    // Branch-scoped lookup: pinned staff sending a test for a sibling
    // branch's campaign would otherwise leak credentials by triggering a
    // send through that branch's WhatsApp/SMTP setup. Sibling-branch IDs
    // get an explicit 403 (vs the 404 a missing UUID returns).
    const c = await loadAccessibleOrThrow(
      await getCampaign(restaurantId, id, effectiveBranchId(req.session)),
      () => getCampaign(restaurantId, id, null),
      'Campaign',
    );

    let to: string | null = null;
    try {
      const body = await req.json();
      if (body && typeof body === 'object' && typeof (body as { to?: unknown }).to === 'string') {
        to = (body as { to: string }).to;
      }
    } catch { /* allow empty body — fall through to session lookup */ }

    if (!to) {
      // Channel-aware fallback. For email we use the operator's own address;
      // for WhatsApp we require an explicit phone in the body — never reuse
      // the email as a phone number, which would surface a confusing
      // provider-side "invalid recipient" error.
      if (c.channel === 'email') {
        const { rows } = await db.execute(sql`
          SELECT email FROM users WHERE id = ${req.session.userId} LIMIT 1
        `);
        to = (rows[0] as { email?: string } | undefined)?.email ?? null;
      }
    }
    if (!to) {
      throw new ValidationError(
        c.channel === 'whatsapp'
          ? 'A WhatsApp phone number (E.164) is required for the test send. Pass { "to": "+1234567890" }.'
          : 'A recipient email is required for the test send.',
      );
    }

    if (c.channel === 'email') {
      if (!c.subject || !c.body_html) throw new ValidationError('Email subject and body are required');
      const result = await sendCampaignEmail({
        to, subject: `[TEST] ${c.subject}`, bodyHtml: c.body_html,
        restaurantId, branchId: c.branch_id, customerId: null,
      });
      if (result.error) throw new ValidationError(`Test send failed: ${result.error}`);
      return NextResponse.json({ ok: true, messageId: result.messageId });
    }

    // WhatsApp
    if (!c.branch_id) throw new ValidationError('WhatsApp campaign requires a branch');
    if (!c.template_name) throw new ValidationError('Template name is required');
    const result = await sendCampaignWhatsApp({
      branchId: c.branch_id, toE164: to,
      templateName: c.template_name, templateLang: c.template_lang ?? 'en',
      templateVars: c.template_vars,
    });
    if (result.error) throw new ValidationError(`Test send failed: ${result.error}`);
    return NextResponse.json({ ok: true, messageId: result.messageId });
  })
);
