"use client";

import { useState, useRef, useEffect, useCallback } from "react";
import { useRouter } from "next/navigation";
import { motion, AnimatePresence } from "framer-motion";
import { Plus, LogIn, Loader2, MapPin, Navigation, X, Users, Heart, Sparkles, ChevronRight, Flame, User } from "lucide-react";
import { getUserId, getCachedProfile, getCachedPreferences } from "@/lib/userId";
import { getAvatarBg } from "@/lib/avatars";
import AuthModal from "@/components/AuthModal";
import BrandLogo from "@/components/BrandLogo";
import { SCENES, getSceneConfig } from "@/lib/sceneConfig";
import type { UserProfile, SceneType } from "@/types";

interface LocationSuggestion {
  id: string;
  name: string;
  district: string;
  address: string;
  lat: number;
  lng: number;
}

type GpsStatus = "idle" | "locating" | "success" | "failed" | "denied";

const DISTANCE_OPTIONS = [
  { label: "1km", value: 1000 },
  { label: "3km", value: 3000 },
  { label: "5km", value: 5000 },
] as const;

type GpsResult =
  | { ok: true; lat: number; lng: number }
  | { ok: false; reason: "unsupported" | "denied" | "timeout" | "unknown" };

function requestGps(): Promise<GpsResult> {
  return new Promise((resolve) => {
    if (!navigator.geolocation) {
      resolve({ ok: false, reason: "unsupported" });
      return;
    }

    navigator.geolocation.getCurrentPosition(
      (pos) =>
        resolve({ ok: true, lat: pos.coords.latitude, lng: pos.coords.longitude }),
      (err) => {
        const reason =
          err.code === err.PERMISSION_DENIED
            ? "denied"
            : err.code === err.TIMEOUT
              ? "timeout"
              : "unknown";
        resolve({ ok: false, reason });
      },
      { timeout: 8000, enableHighAccuracy: false },
    );
  });
}

async function reverseGeocode(lat: number, lng: number): Promise<string | null> {
  try {
    const res = await fetch(`/api/location/regeo?lat=${lat}&lng=${lng}`);
    const data = await res.json();
    return data.name || data.formatted || null;
  } catch {
    return null;
  }
}

export default function LandingPage() {
  const router = useRouter();
  const [roomCode, setRoomCode] = useState("");
  const [loading, setLoading] = useState(false);
  const [loadingText, setLoadingText] = useState("");
  const [error, setError] = useState("");

  const [locationQuery, setLocationQuery] = useState("");
  const [suggestions, setSuggestions] = useState<LocationSuggestion[]>([]);
  const [showSuggestions, setShowSuggestions] = useState(false);
  const [selectedLocation, setSelectedLocation] = useState<LocationSuggestion | null>(null);
  const [fetchingSuggestions, setFetchingSuggestions] = useState(false);
  const [radius, setRadius] = useState(3000);
  const [priceRange, setPriceRange] = useState("any");
  const [cuisine, setCuisine] = useState("");
  const suggestRef = useRef<HTMLDivElement>(null);
  const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);

  const [gpsStatus, setGpsStatus] = useState<GpsStatus>("idle");
  const [gpsCoords, setGpsCoords] = useState<{ lat: number; lng: number } | null>(null);
  const [gpsLocationName, setGpsLocationName] = useState<string | null>(null);

  const [scene, setScene] = useState<SceneType>("eat");
  const sceneConfig = getSceneConfig(scene);

  const [profile, setProfile] = useState<UserProfile | null>(null);
  const [authModalOpen, setAuthModalOpen] = useState(false);

  useEffect(() => {
    const cached = getCachedProfile();
    if (cached) setProfile(cached);

    const prefs = getCachedPreferences();
    if (prefs.cuisine) setCuisine(prefs.cuisine);
    if (prefs.priceRange) setPriceRange(prefs.priceRange);
    if (prefs.radius) setRadius(prefs.radius);
  }, []);

  const handleSceneChange = useCallback((s: SceneType) => {
    setScene(s);
    setCuisine("");
    setPriceRange("any");
  }, []);

  const doGpsLocate = useCallback(async () => {
    setGpsStatus("locating");
    const result = await requestGps();
    if (result.ok) {
      setGpsCoords({ lat: result.lat, lng: result.lng });
      setGpsStatus("success");
      const name = await reverseGeocode(result.lat, result.lng);
      if (name) setGpsLocationName(name);
    } else {
      setGpsCoords(null);
      setGpsLocationName(null);
      setGpsStatus(result.reason === "denied" ? "denied" : "failed");
    }
  }, []);

  useEffect(() => {
    doGpsLocate();
  }, [doGpsLocate]);

  const fetchSuggestions = useCallback(async (query: string) => {
    if (query.length < 1) {
      setSuggestions([]);
      setShowSuggestions(false);
      return;
    }
    setFetchingSuggestions(true);
    try {
      const res = await fetch(`/api/location/suggest?keywords=${encodeURIComponent(query)}`);
      const data: LocationSuggestion[] = await res.json();
      setSuggestions(data);
      setShowSuggestions(data.length > 0);
    } catch {
      setSuggestions([]);
    } finally {
      setFetchingSuggestions(false);
    }
  }, []);

  const handleLocationInput = (val: string) => {
    setLocationQuery(val);
    setSelectedLocation(null);
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => fetchSuggestions(val), 300);
  };

  const handleSelectLocation = (loc: LocationSuggestion) => {
    setSelectedLocation(loc);
    setLocationQuery(loc.name);
    setShowSuggestions(false);
    setSuggestions([]);
  };

  const clearLocation = () => {
    setSelectedLocation(null);
    setLocationQuery("");
    setSuggestions([]);
    setShowSuggestions(false);
  };

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (suggestRef.current && !suggestRef.current.contains(e.target as Node)) {
        setShowSuggestions(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const joinRoom = async (roomId: string) => {
    const userId = getUserId();
    const res = await fetch(`/api/room/${roomId}/join`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userId }),
    });
    if (!res.ok) throw new Error("房间不存在");
    return roomId;
  };

  const handleCreate = async () => {
    setError("");

    let coords: { lat: number; lng: number };

    if (selectedLocation) {
      coords = { lat: selectedLocation.lat, lng: selectedLocation.lng };
    } else if (gpsCoords) {
      coords = gpsCoords;
    } else if (gpsStatus === "locating") {
      setError("正在定位中，请稍候...");
      return;
    } else {
      setError("无法获取位置，请在上方搜索并选择一个地点");
      return;
    }

    setLoading(true);

    try {
      setLoadingText(sceneConfig.loadingText);

      const res = await fetch("/api/room/create", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ...coords, radius, priceRange, cuisine, userId: getUserId(), scene }),
      });

      const data = await res.json();

      if (!res.ok) {
        throw new Error(data.error || "创建房间失败");
      }

      if (!data.roomId) {
        throw new Error("创建房间失败");
      }

      setLoadingText("正在进入房间...");
      await joinRoom(data.roomId);
      router.push(`/room/${data.roomId}`);
    } catch (e) {
      setError(e instanceof Error ? e.message : "创建失败，请重试");
      setLoading(false);
      setLoadingText("");
    }
  };

  const handleJoin = async (e: React.FormEvent) => {
    e.preventDefault();
    if (roomCode.length !== 4) {
      setError("请输入 4 位房间号");
      return;
    }
    setLoading(true);
    setError("");
    try {
      await joinRoom(roomCode);
      router.push(`/room/${roomCode}`);
    } catch {
      setError("房间不存在，请检查房间号");
      setLoading(false);
    }
  };

  return (
    <div className="relative flex min-h-dvh flex-col items-center justify-center bg-background px-6 py-12">
      {/* Profile / Auth button */}
      <div className="absolute right-4 top-4">
        {profile ? (
          <button
            onClick={() => router.push("/profile")}
            className={`flex h-9 items-center gap-1.5 rounded-full px-3 text-sm font-medium transition-colors active:opacity-80 ${getAvatarBg(profile.avatar)}`}
          >
            <span className="text-base leading-none">{profile.avatar}</span>
            <span className="max-w-[5rem] truncate text-xs font-semibold text-zinc-700">{profile.username}</span>
          </button>
        ) : (
          <button
            onClick={() => setAuthModalOpen(true)}
            className="flex h-9 items-center gap-1.5 rounded-full bg-zinc-100 px-3 text-xs font-medium text-zinc-500 transition-colors active:bg-zinc-200"
          >
            <User size={14} />
            登录
          </button>
        )}
      </div>

      <motion.div
        className="flex flex-col items-center"
        initial={{ y: -20, opacity: 0 }}
        animate={{ y: 0, opacity: 1 }}
        transition={{ duration: 0.5 }}
      >
        <BrandLogo size={56} />
        <h1 className="mt-2.5 text-3xl font-black tracking-tight text-zinc-900">
          NoWhatever
        </h1>
        <p className="mt-0.5 text-sm font-medium tracking-widest text-zinc-400">
          别说随便
        </p>
        <p className="mt-3 max-w-xs text-center text-sm leading-relaxed text-zinc-500">
          {sceneConfig.subtitle}
        </p>
      </motion.div>

      <motion.div
        className="mt-8 flex items-start justify-center gap-3"
        initial={{ y: 10, opacity: 0 }}
        animate={{ y: 0, opacity: 1 }}
        transition={{ duration: 0.5, delay: 0.1 }}
      >
        <div className="flex flex-col items-center gap-1.5 w-20">
          <div className="flex h-10 w-10 items-center justify-center rounded-full bg-emerald-50">
            <Users size={18} className="text-emerald-500" />
          </div>
          <span className="text-xs font-semibold text-zinc-700">创建房间</span>
          <span className="text-[10px] leading-tight text-zinc-400 text-center">邀请朋友加入</span>
        </div>

        <ChevronRight size={14} className="mt-3 shrink-0 text-zinc-300" />

        <div className="flex flex-col items-center gap-1.5 w-20">
          <div className="flex h-10 w-10 items-center justify-center rounded-full bg-amber-50">
            <Heart size={18} className="text-amber-500" />
          </div>
          <span className="text-xs font-semibold text-zinc-700">各自滑卡</span>
          <span className="text-[10px] leading-tight text-zinc-400 text-center">右滑喜欢的店</span>
        </div>

        <ChevronRight size={14} className="mt-3 shrink-0 text-zinc-300" />

        <div className="flex flex-col items-center gap-1.5 w-20">
          <div className="flex h-10 w-10 items-center justify-center rounded-full bg-rose-50">
            <Sparkles size={18} className="text-rose-500" />
          </div>
          <span className="text-xs font-semibold text-zinc-700">匹配结果</span>
          <span className="text-[10px] leading-tight text-zinc-400 text-center">滑中同一家就去</span>
        </div>
      </motion.div>

      <motion.div
        className="mt-8 flex items-center justify-center gap-2"
        initial={{ y: 10, opacity: 0 }}
        animate={{ y: 0, opacity: 1 }}
        transition={{ duration: 0.4, delay: 0.12 }}
      >
        {SCENES.map((s) => {
          const cfg = getSceneConfig(s);
          const active = scene === s;
          return (
            <button
              key={s}
              onClick={() => handleSceneChange(s)}
              disabled={loading}
              className={`flex items-center gap-1.5 rounded-full px-4 py-2 text-sm font-semibold transition-all disabled:opacity-50 ${
                active
                  ? "bg-emerald-500 text-white shadow-md shadow-emerald-200"
                  : "bg-zinc-100 text-zinc-500 hover:bg-zinc-200"
              }`}
            >
              <span className="text-base leading-none">{cfg.emoji}</span>
              {cfg.label}
            </button>
          );
        })}
      </motion.div>

      <motion.div
        className="mt-5 flex w-full max-w-xs flex-col gap-3"
        initial={{ y: 20, opacity: 0 }}
        animate={{ y: 0, opacity: 1 }}
        transition={{ duration: 0.5, delay: 0.15 }}
      >
        <div ref={suggestRef} className="relative">
          <div className="relative flex items-center">
            <MapPin size={16} className="absolute left-3 text-zinc-400" />
            <input
              type="text"
              placeholder="搜索位置（默认当前位置）"
              value={locationQuery}
              onChange={(e) => handleLocationInput(e.target.value)}
              onFocus={() => suggestions.length > 0 && setShowSuggestions(true)}
              disabled={loading}
              className="h-10 w-full rounded-xl border border-zinc-200 bg-white pl-9 pr-9 text-sm text-zinc-700 outline-none transition-colors placeholder:text-zinc-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-100 disabled:opacity-50"
            />
            {(selectedLocation || locationQuery) && !loading && (
              <button
                onClick={clearLocation}
                className="absolute right-2.5 flex h-5 w-5 items-center justify-center rounded-full text-zinc-400 hover:text-zinc-600"
              >
                <X size={14} />
              </button>
            )}
            {fetchingSuggestions && (
              <Loader2 size={14} className="absolute right-3 animate-spin text-zinc-300" />
            )}
          </div>

          {selectedLocation && (
            <div className="mt-1.5 flex items-center gap-1.5 px-1">
              <Navigation size={12} className="shrink-0 text-emerald-500" />
              <span className="truncate text-xs text-emerald-600">
                {selectedLocation.district} {selectedLocation.address || selectedLocation.name}
              </span>
            </div>
          )}

          {!selectedLocation && !locationQuery && gpsStatus === "locating" && (
            <div className="mt-1.5 flex items-center gap-1.5 px-1">
              <Loader2 size={12} className="shrink-0 animate-spin text-emerald-400" />
              <span className="text-xs text-zinc-400">正在获取当前位置...</span>
            </div>
          )}

          {!selectedLocation && !locationQuery && gpsStatus === "success" && (
            <div className="mt-1.5 flex items-center gap-1.5 px-1">
              <Navigation size={12} className="shrink-0 text-emerald-500" />
              <span className="truncate text-xs text-emerald-600">
                当前位置：{gpsLocationName || "已定位"}
              </span>
            </div>
          )}

          {!selectedLocation && !locationQuery && (gpsStatus === "failed" || gpsStatus === "denied") && (
            <div className="mt-1.5 flex items-center justify-between px-1">
              <div className="flex items-center gap-1.5">
                <MapPin size={12} className="shrink-0 text-amber-500" />
                <span className="text-xs text-amber-600">
                  {gpsStatus === "denied" ? "定位权限被拒绝" : "定位失败"}，请搜索选择位置
                </span>
              </div>
              <button
                onClick={doGpsLocate}
                className="shrink-0 text-xs font-medium text-emerald-500 active:text-emerald-700"
              >
                重试
              </button>
            </div>
          )}

          {!selectedLocation && !locationQuery && gpsStatus === "idle" && (
            <div className="mt-1.5 flex items-center gap-1.5 px-1">
              <Navigation size={12} className="shrink-0 text-zinc-400" />
              <span className="text-xs text-zinc-400">将使用当前定位</span>
            </div>
          )}

          <AnimatePresence>
            {showSuggestions && (
              <motion.ul
                initial={{ opacity: 0, y: -4 }}
                animate={{ opacity: 1, y: 0 }}
                exit={{ opacity: 0, y: -4 }}
                transition={{ duration: 0.15 }}
                className="absolute left-0 right-0 top-full z-50 mt-1 max-h-56 overflow-y-auto rounded-xl border border-zinc-100 bg-white py-1 shadow-lg"
              >
                {suggestions.map((s) => (
                  <li key={s.id}>
                    <button
                      onClick={() => handleSelectLocation(s)}
                      className="flex w-full items-start gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-emerald-50"
                    >
                      <MapPin size={14} className="mt-0.5 shrink-0 text-zinc-400" />
                      <div className="min-w-0">
                        <p className="truncate text-sm font-medium text-zinc-800">{s.name}</p>
                        <p className="truncate text-xs text-zinc-400">{s.district} {s.address}</p>
                      </div>
                    </button>
                  </li>
                ))}
              </motion.ul>
            )}
          </AnimatePresence>
        </div>

        <div className="flex flex-col gap-2 rounded-xl border border-zinc-100 bg-zinc-50/50 px-3 py-2.5">
          <div className="flex items-center gap-3">
            <span className="w-8 shrink-0 text-xs font-medium text-zinc-400">{sceneConfig.tagLabel}</span>
            <div className="relative flex flex-1 items-center">
              <input
                type="text"
                placeholder={sceneConfig.tagPlaceholder}
                value={cuisine}
                onChange={(e) => setCuisine(e.target.value)}
                disabled={loading}
                className="h-7 w-full rounded-full border-none bg-white pl-3 pr-7 text-xs text-zinc-700 outline-none ring-1 ring-zinc-200 transition-colors placeholder:text-zinc-300 focus:ring-2 focus:ring-emerald-300 disabled:opacity-50"
              />
              {cuisine && !loading && (
                <button
                  onClick={() => setCuisine("")}
                  className="absolute right-2 flex h-4 w-4 items-center justify-center rounded-full text-zinc-400 hover:text-zinc-600"
                >
                  <X size={12} />
                </button>
              )}
            </div>
          </div>

          <div className="flex items-center gap-3">
            <span className="w-8 shrink-0 text-xs font-medium text-zinc-400"></span>
            <div className="flex flex-wrap items-center gap-1.5">
              <Flame size={11} className="shrink-0 text-orange-400" />
              {sceneConfig.hotTags.map((tag) => (
                <button
                  key={tag}
                  type="button"
                  onClick={() => setCuisine(tag)}
                  disabled={loading}
                  className={`h-6 rounded-full px-2.5 text-xs font-medium transition-colors disabled:opacity-50 ${
                    cuisine === tag
                      ? "bg-emerald-500 text-white shadow-sm"
                      : "bg-white text-zinc-500 hover:bg-zinc-200"
                  }`}
                >
                  {tag}
                </button>
              ))}
            </div>
          </div>

          <div className="flex items-center gap-3">
            <span className="w-8 shrink-0 text-xs font-medium text-zinc-400">距离</span>
            <div className="flex gap-1.5">
              {DISTANCE_OPTIONS.map((opt) => (
                <button
                  key={opt.value}
                  type="button"
                  onClick={() => setRadius(opt.value)}
                  disabled={loading}
                  className={`h-7 rounded-full px-3 text-xs font-medium transition-colors disabled:opacity-50 ${
                    radius === opt.value
                      ? "bg-emerald-500 text-white shadow-sm"
                      : "bg-white text-zinc-500 hover:bg-zinc-200"
                  }`}
                >
                  {opt.label}
                </button>
              ))}
            </div>
          </div>

          <div className="flex items-center gap-3">
            <span className="w-8 shrink-0 text-xs font-medium text-zinc-400">人均</span>
            <div className="flex flex-wrap gap-1.5">
              {sceneConfig.priceOptions.map((opt) => (
                <button
                  key={opt.value}
                  type="button"
                  onClick={() => setPriceRange(opt.value)}
                  disabled={loading}
                  className={`h-7 rounded-full px-3 text-xs font-medium transition-colors disabled:opacity-50 ${
                    priceRange === opt.value
                      ? "bg-emerald-500 text-white shadow-sm"
                      : "bg-white text-zinc-500 hover:bg-zinc-200"
                  }`}
                >
                  {opt.label}
                </button>
              ))}
            </div>
          </div>

        </div>

        <button
          onClick={handleCreate}
          disabled={loading}
          className="flex h-12 w-full items-center justify-center gap-2 rounded-xl bg-emerald-500 text-sm font-bold text-white shadow-md shadow-emerald-200 transition-colors hover:bg-emerald-600 disabled:opacity-50"
        >
          {loading && loadingText ? (
            <>
              <Loader2 size={18} className="animate-spin" />
              {loadingText}
            </>
          ) : (
            <>
              <Plus size={18} strokeWidth={3} />
              创建新房间
            </>
          )}
        </button>

        <div className="flex items-center gap-3 py-2">
          <div className="h-px flex-1 bg-zinc-200" />
          <span className="text-xs text-zinc-400">或加入已有房间</span>
          <div className="h-px flex-1 bg-zinc-200" />
        </div>

        <form onSubmit={handleJoin} className="flex gap-2">
          <input
            type="text"
            inputMode="numeric"
            pattern="[0-9]*"
            maxLength={4}
            placeholder="输入 4 位房间号"
            value={roomCode}
            onChange={(e) => {
              setRoomCode(e.target.value.replace(/\D/g, "").slice(0, 4));
              setError("");
            }}
            disabled={loading}
            className="h-12 flex-1 rounded-xl border border-zinc-200 bg-white px-4 text-center text-lg font-semibold tracking-[0.3em] text-zinc-900 outline-none transition-colors placeholder:text-sm placeholder:tracking-normal placeholder:text-zinc-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-100 disabled:opacity-50"
          />
          <button
            type="submit"
            disabled={loading || roomCode.length !== 4}
            className="flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-900 text-white transition-colors hover:bg-zinc-700 disabled:opacity-30"
          >
            <LogIn size={18} />
          </button>
        </form>

        {error && (
          <motion.p
            className="text-center text-xs font-medium text-rose-500"
            initial={{ opacity: 0, y: -4 }}
            animate={{ opacity: 1, y: 0 }}
          >
            {error}
          </motion.p>
        )}
      </motion.div>

      <AuthModal
        open={authModalOpen}
        onClose={() => setAuthModalOpen(false)}
        onAuth={(p) => setProfile(p)}
      />
    </div>
  );
}
