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 { updateSegmentSchema } from '@server/validators/marketing.validator';
import { getSegment, updateSegment, deleteSegment } from '@server/services/marketing/segments.service';
import { effectiveBranchId, loadAccessibleOrThrow, scopeAudienceRules } from '@server/utils/branch-access';

export const GET = withErrorHandler(
  withAuth(async (req: AuthedRequest, ctx: RouteContext) => {
    const restaurantId = req.session.restaurantId!;
    await requireSection(req, 'marketing');
    await requirePlanFeature(restaurantId, 'marketing');
    const { id } = await ctx.params;
    // Scoped lookup first; if the segment exists in this restaurant but
    // belongs to a sibling branch, loadAccessibleOrThrow distinguishes
    // 403 from 404 (instead of leaking sibling-branch IDs as "not found").
    const segment = await loadAccessibleOrThrow(
      await getSegment(restaurantId, id, effectiveBranchId(req.session)),
      () => getSegment(restaurantId, id, null),
      'Segment',
    );
    return NextResponse.json({ segment });
  })
);

export const PUT = withErrorHandler(
  withAuth(
    withValidationAuthed(updateSegmentSchema, async (req, ctx: RouteContext) => {
      const restaurantId = req.session.restaurantId!;
      await requireSection(req, 'marketing', 'update');
      await requirePlanFeature(restaurantId, 'marketing');
      const { id } = await ctx.params;
      // Pre-flight: 403 on sibling-branch IDs, 404 on truly missing IDs.
      await loadAccessibleOrThrow(
        await getSegment(restaurantId, id, effectiveBranchId(req.session)),
        () => getSegment(restaurantId, id, null),
        'Segment',
      );
      const body = req.parsedBody as { name?: string; description?: string | null; rules?: { branchIds?: string[] | null } & Record<string, unknown> };
      // Re-scope rules.branchIds — without this a pinned user could PUT a
      // crafted rules payload that targets sibling-branch customers, even
      // though the segment row itself stays pinned to their branch.
      const patch = body.rules !== undefined
        ? { ...body, rules: scopeAudienceRules(req.session, body.rules) }
        : body;
      const segment = await updateSegment(restaurantId, id, patch, effectiveBranchId(req.session));
      return NextResponse.json({ segment });
    })
  )
);

export const DELETE = withErrorHandler(
  withAuth(async (req: AuthedRequest, ctx: RouteContext) => {
    const restaurantId = req.session.restaurantId!;
    await requireSection(req, 'marketing', 'delete');
    await requirePlanFeature(restaurantId, 'marketing');
    const { id } = await ctx.params;
    await loadAccessibleOrThrow(
      await getSegment(restaurantId, id, effectiveBranchId(req.session)),
      () => getSegment(restaurantId, id, null),
      'Segment',
    );
    // The service detaches non-completed campaigns inline (Task #239) and
    // returns their IDs so the client can let the operator know how many
    // active campaigns were just untethered from this audience.
    const { detachedCampaignIds } = await deleteSegment(restaurantId, id, effectiveBranchId(req.session));
    return NextResponse.json({ success: true, detachedCampaignIds });
  })
);
