import { NextResponse } from "next/server";
import { createRoom } from "@/lib/store";
import { Restaurant, SceneType } from "@/types";
import { getSceneConfig } from "@/lib/sceneConfig";
import { apiHandler, ApiError } from "@/lib/api";
import { requireAmapApiKey } from "@/lib/amap";

interface AmapPoiV5 {
  id: string;
  name: string;
  distance?: string;
  type?: string;
  address?: string;
  location?: string;
  business?: {
    rating?: string;
    cost?: string;
    opentime_today?: string;
    opentime_week?: string;
    tel?: string;
    tag?: string;
  };
  photos?: { url: string }[];
}

function extractCategory(type?: string): string {
  if (!type) return "";
  const parts = type.split(";");
  return parts[parts.length - 1] || parts[1] || "";
}

function cleanField(val: unknown): string {
  if (!val || val === "[]" || (Array.isArray(val) && val.length === 0))
    return "";
  return String(val);
}

function mapPoiToRestaurant(poi: AmapPoiV5, defaultImage: string): Restaurant {
  const ratingStr = poi.business?.rating;
  const rating =
    ratingStr && ratingStr !== "[]" ? parseFloat(ratingStr) || 4.0 : 4.0;

  const costStr = poi.business?.cost;
  const price =
    costStr && costStr !== "[]" && costStr !== "0" ? `¥${costStr}` : "未知";

  const images =
    poi.photos && poi.photos.length > 0
      ? poi.photos
          .map((p) => p.url)
          .filter(Boolean)
          .slice(0, 5)
      : [];
  if (images.length === 0) images.push(defaultImage);

  const openTime =
    cleanField(poi.business?.opentime_week) ||
    cleanField(poi.business?.opentime_today);

  return {
    id: poi.id,
    name: poi.name,
    rating,
    price,
    distance: poi.distance ? `${poi.distance}m` : "",
    images,
    category: extractCategory(poi.type),
    address: cleanField(poi.address),
    openTime,
    tel: cleanField(poi.business?.tel),
    tag: cleanField(poi.business?.tag),
    location: cleanField(poi.location),
  };
}

function filterByPrice(
  restaurants: Restaurant[],
  priceRange: string,
): Restaurant[] {
  if (priceRange === "any") return restaurants;

  return restaurants.filter((r) => {
    if (r.price === "未知") return true;
    const cost = parseInt(r.price.replace(/[¥￥]/g, ""), 10);
    if (isNaN(cost)) return true;

    switch (priceRange) {
      case "under20":
        return cost < 20;
      case "under50":
        return cost < 50;
      case "20to50":
        return cost >= 20 && cost <= 50;
      case "50to100":
        return cost >= 50 && cost <= 100;
      case "over50":
        return cost > 50;
      case "over100":
        return cost > 100;
      default:
        return true;
    }
  });
}

export const POST = apiHandler(async (req) => {
  const body = await req.json();
  const {
    lat,
    lng,
    radius = 3000,
    priceRange = "any",
    cuisine = "不限",
    userId = "",
    scene = "eat" as SceneType,
  } = body;

  const sceneConfig = getSceneConfig(scene);

  const numLat = Number(lat);
  const numLng = Number(lng);
  if (!Number.isFinite(numLat) || !Number.isFinite(numLng) ||
      numLat < -90 || numLat > 90 || numLng < -180 || numLng > 180) {
    throw new ApiError("无法获取位置信息，请允许定位权限后重试");
  }

  const apiKey = requireAmapApiKey();

  const url = new URL("https://restapi.amap.com/v5/place/around");
  url.searchParams.set("key", apiKey);
  url.searchParams.set("location", `${numLng},${numLat}`);
  url.searchParams.set("radius", String(radius));
  url.searchParams.set("types", sceneConfig.poiTypes);
  url.searchParams.set("show_fields", "business,photos");
  url.searchParams.set("sortrule", "weight");

  const needsPriceFilter = priceRange !== "any";
  url.searchParams.set("page_size", needsPriceFilter ? "25" : "15");

  if (cuisine && cuisine !== "不限") {
    url.searchParams.set("keywords", cuisine);
  }

  let amapData;
  try {
    const amapRes = await fetch(url.toString());
    amapData = await amapRes.json();
  } catch {
    throw new ApiError("位置服务暂时不可用，请稍后重试", 503);
  }

  let restaurants: Restaurant[] = [];
  if (amapData.status === "1" && amapData.pois?.length > 0) {
    let results: Restaurant[] = amapData.pois.map(
      (poi: AmapPoiV5) => mapPoiToRestaurant(poi, sceneConfig.defaultImage),
    );
    results = filterByPrice(results, priceRange);
    restaurants = results.slice(0, 15);
  }

  if (restaurants.length === 0) throw new ApiError(sceneConfig.emptyError, 404);

  const roomId = await createRoom(restaurants, userId, sceneConfig.key);
  return NextResponse.json({ roomId, restaurants });
});
