import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { getCurrentUser } from "@/lib/auth";
import { listAccessibleBrands } from "@/lib/brand-access";
import { sanitizeBrandArray, deriveLegacyLocation, deriveLegacyServiceType } from "@/lib/brand-helpers";

// GET /api/brands?orgId=xxx — list brands in an org
// Filters to only brands the caller has access to: org owner/admin
// see every brand; members only see brands they have an explicit
// BrandMembership for. Prevents a 4-seat Growth org from leaking
// every brand into every member's sidebar.
export const dynamic = "force-dynamic";

export async function GET(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const { searchParams } = new URL(req.url);
  const orgId = searchParams.get("orgId");

  if (!orgId) {
    return NextResponse.json({ error: "orgId is required" }, { status: 400 });
  }

  // Membership check now rolls into listAccessibleBrands — a user
  // with no membership gets an empty list rather than a 403, which
  // simplifies the sidebar's empty-state handling.
  let accessible = await listAccessibleBrands(user.id, orgId);

  if (accessible.length === 0) {
    const membership = await prisma.orgMembership.findUnique({
      where: { userId_orgId: { userId: user.id, orgId } },
    });
    if (!membership) {
      // Last resort: find ANY org this user owns and return its brands
      const ownedOrg = await prisma.orgMembership.findFirst({
        where: { userId: user.id, role: "owner" },
        select: { orgId: true },
      });
      if (ownedOrg) {
        console.warn("[/api/brands] Owner found via fallback", { userId: user.id, ownedOrgId: ownedOrg.orgId, requestedOrgId: orgId });
        accessible = await prisma.brand.findMany({
          where: { orgId: ownedOrg.orgId },
          orderBy: { createdAt: "asc" },
        });
      }
      if (accessible.length === 0) {
        return NextResponse.json({ error: "Not a member of this organization" }, { status: 403 });
      }
    }
  }

  // Re-fetch with the same includes the UI expects. listAccessibleBrands
  // returns bare Brand rows; doing the hydrated query here keeps all
  // other consumers untouched.
  const brands = await prisma.brand.findMany({
    where: { id: { in: accessible.map((b) => b.id) } },
    include: {
      websites: true,
      dashboardData: true,
      profile: {
        select: { logoUrl: true, primaryColor: true, secondaryColor: true, fontFamily: true, industry: true, shortDescription: true, brandVoice: true },
      },
      integrations: {
        select: { integrationId: true, connected: true, status: true, lastSynced: true },
      },
      trackedSite: {
        select: { siteId: true, status: true, lastEventAt: true },
      },
    },
    orderBy: { createdAt: "desc" },
  });

  // Site-tag-has-data check: use the already-loaded trackedSite.lastEventAt
  // instead of querying SiteEvent (which has 30M+ rows and causes timeouts).
  const enriched = brands.map((brand) => ({
    ...brand,
    siteTagHasData: !!brand.trackedSite?.lastEventAt,
  }));

  return NextResponse.json(enriched);
}

// POST /api/brands — create a new brand in an org
//
// Accepts both the legacy single-string fields (location, serviceType)
// and the multi-value array fields (locations, primaryServices,
// secondaryServices). Arrays win when non-empty; legacy fields are
// kept in sync so consumers that haven't migrated to the helpers in
// @/lib/brand-helpers continue to read sensible values.
export async function POST(req: Request) {
  const user = await getCurrentUser();
  if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  try {
    const body = await req.json();
    const { orgId, name, domain, industry, serviceType, location } = body;

    if (!orgId || !name?.trim() || !domain?.trim()) {
      return NextResponse.json({ error: "orgId, name, and domain are required" }, { status: 400 });
    }

    // Verify user is a member of this org
    const membership = await prisma.orgMembership.findUnique({
      where: { userId_orgId: { userId: user.id, orgId } },
    });

    if (!membership) {
      return NextResponse.json({ error: "Not a member of this organization" }, { status: 403 });
    }

    // Inherit plan from the org — new brands should not fall back to the
    // schema default ("trial") when the org is already on a paid plan.
    const VALID_BRAND_PLANS = ["trial", "growth", "professional", "agency", "agency_pro", "enterprise"];
    const org = await prisma.organization.findUnique({
      where: { id: orgId },
      select: { plan: true },
    });
    if (!org) return NextResponse.json({ error: "Organization not found" }, { status: 404 });
    const inheritedPlan = VALID_BRAND_PLANS.includes(org.plan) ? org.plan : "trial";

    // Sanitize array inputs first so a bad payload returns a
    // structured 400 instead of a Prisma validation error.
    const locationsCheck = sanitizeBrandArray(body.locations, "locations");
    if (!locationsCheck.ok) return NextResponse.json({ error: locationsCheck.error }, { status: 400 });
    const primaryCheck = sanitizeBrandArray(body.primaryServices, "primaryServices");
    if (!primaryCheck.ok) return NextResponse.json({ error: primaryCheck.error }, { status: 400 });
    const secondaryCheck = sanitizeBrandArray(body.secondaryServices, "secondaryServices");
    if (!secondaryCheck.ok) return NextResponse.json({ error: secondaryCheck.error }, { status: 400 });

    const finalLocations = locationsCheck.value.length > 0
      ? locationsCheck.value
      : (typeof location === "string" && location.trim() ? [location.trim()] : []);
    const finalPrimary = primaryCheck.value.length > 0
      ? primaryCheck.value
      : (typeof serviceType === "string" && serviceType.trim()
          ? [serviceType.split(",")[0].trim()].filter(Boolean)
          : []);
    const finalSecondary = secondaryCheck.value.length > 0
      ? secondaryCheck.value
      : (typeof serviceType === "string" && serviceType.includes(",")
          ? serviceType.split(",").slice(1).map((s: string) => s.trim()).filter(Boolean)
          : []);
    const legacyLocation = deriveLegacyLocation(finalLocations, location);
    const legacyServiceType = deriveLegacyServiceType(finalPrimary, serviceType);

    // Generate initials from name
    const words = name.trim().split(/\s+/);
    const initials = words.length >= 2
      ? (words[0][0] + words[1][0]).toUpperCase()
      : name.trim().substring(0, 2).toUpperCase();

    const brand = await prisma.brand.create({
      data: {
        name: name.trim(),
        domain: domain.trim().replace(/^https?:\/\//, ""),
        industry: industry || null,
        serviceType: legacyServiceType,
        location: legacyLocation,
        locations: finalLocations,
        primaryServices: finalPrimary,
        secondaryServices: finalSecondary,
        initials,
        plan: inheritedPlan,
        orgId,
        websites: {
          create: {
            url: domain.trim().startsWith("http") ? domain.trim() : `https://${domain.trim()}`,
            isPrimary: true,
          },
        },
        // Grant the creator explicit access. Owners already see
        // every brand via the org-role shortcut, but a Member who
        // creates a brand would otherwise lose visibility the
        // second /api/brands filters them out. Admins also get a
        // row to keep the Team tab's access matrix honest.
        memberships: {
          create: { userId: user.id, role: "owner" },
        },
      },
      include: { websites: true },
    });

    return NextResponse.json(brand, { status: 201 });
  } catch {
    return NextResponse.json({ error: "Something went wrong" }, { status: 500 });
  }
}
