import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

interface Business {
  place_id: string;
  name: string;
  address: string;
  rating: number;
  review_count: number;
  category: string;
  maps_url: string;
}

const GOOGLE_MAPS_URL_PATTERN =
  /(?:google\.com\/maps|maps\.google\.com|goo\.gl\/maps|maps\.app\.goo\.gl)/i;

function isGoogleMapsUrl(input: string): boolean {
  return GOOGLE_MAPS_URL_PATTERN.test(input);
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { query } = body as { query: string };

    if (!query || typeof query !== "string" || query.trim().length < 2) {
      return NextResponse.json(
        { error: "Query must be at least 2 characters" },
        { status: 400 },
      );
    }

    const trimmed = query.trim();

    if (isGoogleMapsUrl(trimmed)) {
      return handleUrlSearch(trimmed);
    }

    return handleTextSearch(trimmed);
  } catch {
    return NextResponse.json(
      { error: "Invalid request body" },
      { status: 400 },
    );
  }
}

async function handleUrlSearch(url: string): Promise<NextResponse> {
  const engineUrl = process.env.NEXT_PUBLIC_ENGINE_URL;

  if (!engineUrl) {
    return NextResponse.json(
      { error: "Engine service not configured" },
      { status: 503 },
    );
  }

  try {
    const response = await fetch(`${engineUrl}/api/check-reviews`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ url }),
    });

    if (!response.ok) {
      return NextResponse.json(
        { error: "Could not find business from URL" },
        { status: 404 },
      );
    }

    const data = (await response.json()) as Record<string, unknown>;

    const business: Business = {
      place_id: (data.place_id as string) || "",
      name: (data.name as string) || "Unknown Business",
      address: (data.address as string) || "",
      rating: (data.rating as number) || 0,
      review_count: (data.review_count as number) || (data.reviews_count as number) || 0,
      category: (data.category as string) || (data.type as string) || "",
      maps_url: url,
    };

    return NextResponse.json({ businesses: [business] });
  } catch {
    return NextResponse.json(
      { error: "Failed to fetch business details" },
      { status: 502 },
    );
  }
}

async function handleTextSearch(query: string): Promise<NextResponse> {
  const apiKey = process.env.GOOGLE_PLACES_API_KEY;

  if (!apiKey) {
    return NextResponse.json(
      { error: "Places search not configured" },
      { status: 503 },
    );
  }

  try {
    const response = await fetch(
      "https://places.googleapis.com/v1/places:searchText",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-Goog-Api-Key": apiKey,
          "X-Goog-FieldMask":
            "places.id,places.displayName,places.formattedAddress,places.rating,places.userRatingCount,places.primaryTypeDisplayName,places.googleMapsUri",
        },
        body: JSON.stringify({
          textQuery: query,
          languageCode: "en",
        }),
      },
    );

    if (!response.ok) {
      return NextResponse.json(
        { error: "Places search failed" },
        { status: 502 },
      );
    }

    const data = (await response.json()) as Record<string, unknown>;

    const businesses: Business[] = ((data.places as any[]) || [])
      .slice(0, 5)
      .map((place: any) => ({
        place_id: place.id || "",
        name: place.displayName?.text || "Unknown",
        address: place.formattedAddress || "",
        rating: place.rating || 0,
        review_count: place.userRatingCount || 0,
        category: place.primaryTypeDisplayName?.text || "",
        maps_url: place.googleMapsUri || "",
      }));

    return NextResponse.json({ businesses });
  } catch {
    return NextResponse.json(
      { error: "Failed to search businesses" },
      { status: 502 },
    );
  }
}
