/**
 * POST /api/admin/backfill-brand-arrays
 *
 * One-shot backfill that populates the new Brand array fields
 * (locations / primaryServices / secondaryServices) from the legacy
 * single-string fields (location / serviceType) for brands created
 * before the multi-array intake UX shipped.
 *
 * Idempotent — only fills empty arrays. Brands whose array fields
 * already have data are left untouched on re-run.
 *
 * Query params:
 *   ?dryRun=true   — return the per-brand "what WOULD be set"
 *                    preview without writing to the DB.
 *   (default)      — perform the writes.
 *
 * Backfill rules (mirror the helpers in @/lib/brand-helpers):
 *   • locations          ← [location]                 when locations is empty AND location is non-null
 *   • primaryServices    ← [first comma-split token]  when primaryServices is empty AND serviceType is non-null
 *   • secondaryServices  ← [remaining tokens]         when secondaryServices is empty AND serviceType has commas
 *
 * Response:
 *   {
 *     dryRun: boolean,
 *     totalBrands: number,
 *     brandsBackfilled: number,
 *     perBrand: [{
 *       brandId, name,
 *       changes: {
 *         locations?:         { from: string[], to: string[] },
 *         primaryServices?:   { from: string[], to: string[] },
 *         secondaryServices?: { from: string[], to: string[] },
 *       }
 *     }]
 *   }
 *
 * Only brands with at least one change appear in `perBrand`.
 *
 * Auth: superadmin only — same Clerk-session gate as every other
 * /api/admin/* endpoint.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireSuperadmin } from "@/lib/admin-auth";

export const dynamic = "force-dynamic";
export const maxDuration = 60;

type ChangeSet = {
  locations?: { from: string[]; to: string[] };
  primaryServices?: { from: string[]; to: string[] };
  secondaryServices?: { from: string[]; to: string[] };
};

interface PerBrandRow {
  brandId: string;
  name: string;
  changes: ChangeSet;
}

export async function POST(req: Request) {
  const denied = await requireSuperadmin();
  if (denied) return denied;

  const dryRun = new URL(req.url).searchParams.get("dryRun") === "true";

  const brands = await prisma.brand.findMany({
    where: { status: { not: "deleted" } },
    select: {
      id: true,
      name: true,
      location: true,
      serviceType: true,
      locations: true,
      primaryServices: true,
      secondaryServices: true,
    },
    orderBy: { createdAt: "asc" },
  });

  const perBrand: PerBrandRow[] = [];

  for (const b of brands) {
    const changes: ChangeSet = {};

    // Rule 1: locations[] from location
    if ((b.locations?.length ?? 0) === 0 && b.location && b.location.trim()) {
      changes.locations = {
        from: b.locations ?? [],
        to: [b.location.trim()],
      };
    }

    // Rule 2 + 3: primaryServices[] / secondaryServices[] from
    // serviceType, splitting on commas. We compute both at once so
    // a brand whose serviceType is "Lawn Care, Pest Control" lands
    // primaryServices=["Lawn Care"], secondaryServices=["Pest Control"]
    // in a single pass.
    const hasPrimary = (b.primaryServices?.length ?? 0) > 0;
    const hasSecondary = (b.secondaryServices?.length ?? 0) > 0;
    if ((!hasPrimary || !hasSecondary) && b.serviceType && b.serviceType.trim()) {
      const tokens = b.serviceType.split(",").map((s) => s.trim()).filter(Boolean);
      if (tokens.length > 0) {
        if (!hasPrimary) {
          changes.primaryServices = {
            from: b.primaryServices ?? [],
            to: tokens.slice(0, 1),
          };
        }
        if (!hasSecondary && tokens.length > 1) {
          changes.secondaryServices = {
            from: b.secondaryServices ?? [],
            to: tokens.slice(1),
          };
        }
      }
    }

    if (Object.keys(changes).length === 0) continue;
    perBrand.push({ brandId: b.id, name: b.name, changes });
  }

  // Apply writes only when dryRun is false. Each write is scoped to
  // the brand and only touches the array columns we computed, so an
  // unrelated PATCH happening concurrently can't be clobbered.
  if (!dryRun) {
    for (const row of perBrand) {
      const data: Record<string, unknown> = {};
      if (row.changes.locations) data.locations = row.changes.locations.to;
      if (row.changes.primaryServices) data.primaryServices = row.changes.primaryServices.to;
      if (row.changes.secondaryServices) data.secondaryServices = row.changes.secondaryServices.to;
      await prisma.brand.update({ where: { id: row.brandId }, data });
    }
  }

  return NextResponse.json({
    dryRun,
    totalBrands: brands.length,
    brandsBackfilled: perBrand.length,
    perBrand,
  });
}
