import { NextResponse } from 'next/server';
import { withErrorHandler, RouteContext } from '@server/middleware/withErrorHandler';
import { withAuth, requireSection, AuthedRequest } from '@server/middleware/withAuth';
import { withValidationAuthed } from '@server/middleware/withValidation';
import { requirePlanFeature } from '@server/utils/features';
import { launchCampaignSchema, type LaunchCampaignInput } from '@server/validators/marketing.validator';
import { launchCampaign, cancelCampaign, getCampaign } from '@server/services/marketing/campaigns.service';
import { effectiveBranchId, loadAccessibleOrThrow } from '@server/utils/branch-access';

/**
 * launchCampaign / cancelCampaign internally call getCampaign with only a
 * restaurant_id filter, so a pinned-staff user could otherwise launch or
 * cancel a sibling-branch broadcast by guessing the UUID. Pre-flight on
 * the scoped getter; sibling-branch IDs return an explicit 403 (vs the
 * 404 a truly missing UUID returns) via loadAccessibleOrThrow.
 */
async function ensureAccessible(req: AuthedRequest, id: string) {
  const restaurantId = req.session.restaurantId!;
  await loadAccessibleOrThrow(
    await getCampaign(restaurantId, id, effectiveBranchId(req.session)),
    () => getCampaign(restaurantId, id, null),
    'Campaign',
  );
}

export const POST = withErrorHandler(
  withAuth(
    withValidationAuthed(launchCampaignSchema, async (req, ctx: RouteContext) => {
      const restaurantId = req.session.restaurantId!;
      await requireSection(req, 'marketing', 'update');
      await requirePlanFeature(restaurantId, 'marketing');
      const { id } = await ctx.params;
      await ensureAccessible(req, id);
      const body = req.parsedBody as LaunchCampaignInput;
      const campaign = await launchCampaign(restaurantId, id, {
        sendNow: body.sendNow,
        scheduledAt: body.scheduledAt ?? null,
      });
      return NextResponse.json({ campaign });
    })
  )
);

// Convenience: DELETE on the launch sub-resource cancels the broadcast.
export const DELETE = withErrorHandler(
  withAuth(async (req: AuthedRequest, ctx: RouteContext) => {
    const restaurantId = req.session.restaurantId!;
    await requireSection(req, 'marketing', 'update');
    await requirePlanFeature(restaurantId, 'marketing');
    const { id } = await ctx.params;
    await ensureAccessible(req, id);
    const campaign = await cancelCampaign(restaurantId, id);
    return NextResponse.json({ campaign });
  })
);
