import { NextResponse } from 'next/server';
import { z } from 'zod';
import { withErrorHandler } from '@server/middleware/withErrorHandler';
import { withAuth, requireSection, AuthedRequest } from '@server/middleware/withAuth';
import { withValidationAuthed } from '@server/middleware/withValidation';
import { ForbiddenError } from '@server/errors';
import { requirePlanFeature } from '@server/utils/features';
import { getSettings, updateSettings, listTiers } from '@server/services/loyalty.service';

// Loyalty rules drive what customers earn / can redeem — treated as a
// privileged financial setting. Staff can view but cannot mutate.
const CONFIG_ROLES = new Set(['owner', 'manager', 'superadmin', 'support']);

export const GET = withErrorHandler(
  withAuth(async (req: AuthedRequest) => {
    const { restaurantId } = req.session;
    await requireSection(req, 'loyalty');
    await requirePlanFeature(restaurantId!, 'loyalty');
    const [settings, tiers] = await Promise.all([
      getSettings(restaurantId!),
      listTiers(restaurantId!),
    ]);
    return NextResponse.json({ settings, tiers });
  })
);

const updateSettingsSchema = z.object({
  enabled: z.boolean().optional(),
  earn_mode: z.enum(['per_dollar', 'per_order', 'per_item']).optional(),
  earn_rate: z.number().min(0).optional(),
  redeem_points_per_unit: z.number().int().positive().optional(),
  redeem_unit_value: z.number().positive().optional(),
  expiry_months: z.number().int().min(1).nullable().optional(),
  min_redeem_points: z.number().int().min(0).optional(),
  eligibility_order_types: z.array(z.string()).optional(),
  eligibility_channels: z.array(z.string()).optional(),
  tier_threshold_mode: z.enum(['lifetime_points', 'rolling_12mo_spend']).optional(),
  notify_on_earn: z.boolean().optional(),
  notify_on_tier_up: z.boolean().optional(),
});

export const PUT = withErrorHandler(
  withAuth(
    withValidationAuthed(updateSettingsSchema, async (req) => {
      const { restaurantId, role } = req.session;
      if (!role || !CONFIG_ROLES.has(role)) {
        throw new ForbiddenError('Only owners or managers can modify loyalty settings');
      }
      await requireSection(req, 'loyalty', 'update');
      await requirePlanFeature(restaurantId!, 'loyalty');
      const settings = await updateSettings(restaurantId!, req.parsedBody);
      return NextResponse.json({ settings });
    })
  )
);
