"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { GoogleLogin } from "@react-oauth/google";
import LoginMenu from "@/components/LoginMenu";
import { api } from "@/lib/api";
import type { Restaurant, Channel, Review } from "@/lib/api";
import { useAuth } from "@/lib/auth-context";
import MapView, { MapBounds, FlyTo } from "@/components/MapView";
import SearchBar from "@/components/SearchBar";
import RestaurantList from "@/components/RestaurantList";
import RestaurantDetail from "@/components/RestaurantDetail";
import MyReviewsList from "@/components/MyReviewsList";
import BottomSheet from "@/components/BottomSheet";
import { getCuisineIcon } from "@/lib/cuisine-icons";

const CUISINE_TAXONOMY: { category: string; items: string[] }[] = [
  { category: "한식", items: ["백반/한정식", "국밥/해장국", "찌개/전골/탕", "삼겹살/돼지구이", "소고기/한우구이", "곱창/막창", "닭/오리구이", "족발/보쌈", "회/횟집", "해산물", "분식", "면", "죽/죽집", "순대/순대국", "장어/민물", "주점/포차", "파인다이닝/코스"] },
  { category: "일식", items: ["스시/오마카세", "라멘", "돈카츠", "텐동/튀김", "이자카야", "야키니쿠", "카레", "소바/우동", "파인다이닝/코스"] },
  { category: "중식", items: ["중화요리", "마라/훠궈", "딤섬/만두", "양꼬치", "파인다이닝/코스"] },
  { category: "양식", items: ["파스타/이탈리안", "스테이크", "햄버거", "피자", "프렌치", "바베큐", "브런치", "비건/샐러드", "파인다이닝/코스"] },
  { category: "아시아", items: ["베트남", "태국", "인도/중동", "동남아기타"] },
  { category: "기타", items: ["치킨", "카페/디저트", "베이커리", "뷔페", "퓨전"] },
];

function matchCuisineFilter(cuisineType: string | null, filter: string): boolean {
  if (!cuisineType || !filter) return false;
  // filter can be a category ("한식") or full type ("한식|백반/한정식")
  if (filter.includes("|")) return cuisineType === filter;
  return cuisineType.startsWith(filter);
}

const PRICE_GROUPS: { label: string; test: (p: string) => boolean }[] = [
  {
    label: "저렴 (~1만원)",
    test: (p) => /저렴|가성비|착한|만원 이하|[3-9]천원|^\d[,.]?\d*천원/.test(p) || /^[1]만원대$/.test(p) || /^[5-9],?\d{3}원/.test(p),
  },
  {
    label: "보통 (1~3만원)",
    test: (p) => /[1-2]만원대|1-[23]만|인당 [12]\d?,?\d*원|1[2-9],?\d{3}원|2[0-9],?\d{3}원/.test(p),
  },
  {
    label: "고가 (3만원~)",
    test: (p) => /[3-9]만원|고가|높은|묵직|살벌|10만원|5만원|4만원|6만원/.test(p),
  },
];

function matchPriceGroup(priceRange: string | null, group: string): boolean {
  if (!priceRange) return false;
  const g = PRICE_GROUPS.find((g) => g.label === group);
  if (!g) return false;
  return g.test(priceRange);
}

/** Parse pipe-delimited region "나라|시|구" into parts. */
function parseRegion(region: string | null): { country: string; city: string; district: string } | null {
  if (!region) return null;
  const parts = region.split("|");
  return {
    country: parts[0] || "",
    city: parts[1] || "",
    district: parts[2] || "",
  };
}

/** Build 3-level tree: country → city → district[] */
function buildRegionTree(restaurants: Restaurant[]) {
  const tree = new Map<string, Map<string, Set<string>>>();
  for (const r of restaurants) {
    const p = parseRegion(r.region);
    if (!p || !p.country) continue;
    if (!tree.has(p.country)) tree.set(p.country, new Map());
    const cityMap = tree.get(p.country)!;
    if (p.city) {
      if (!cityMap.has(p.city)) cityMap.set(p.city, new Set());
      if (p.district) cityMap.get(p.city)!.add(p.district);
    }
  }
  return tree;
}

/** Compute centroid + appropriate zoom from a set of restaurants. */
function computeFlyTo(rests: Restaurant[]): FlyTo | null {
  if (rests.length === 0) return null;
  const lat = rests.reduce((s, r) => s + r.latitude, 0) / rests.length;
  const lng = rests.reduce((s, r) => s + r.longitude, 0) / rests.length;
  // Pick zoom based on geographic spread
  const latSpread = Math.max(...rests.map((r) => r.latitude)) - Math.min(...rests.map((r) => r.latitude));
  const lngSpread = Math.max(...rests.map((r) => r.longitude)) - Math.min(...rests.map((r) => r.longitude));
  const spread = Math.max(latSpread, lngSpread);
  let zoom = 13;
  if (spread > 2) zoom = 8;
  else if (spread > 1) zoom = 9;
  else if (spread > 0.5) zoom = 10;
  else if (spread > 0.2) zoom = 11;
  else if (spread > 0.1) zoom = 12;
  else if (spread > 0.02) zoom = 14;
  else zoom = 15;
  return { lat, lng, zoom };
}

/** Find best matching country + city from user's coordinates using restaurant data. */
function findRegionFromCoords(
  lat: number,
  lng: number,
  restaurants: Restaurant[],
): { country: string; city: string } | null {
  // Group restaurants by country|city and compute centroids
  const groups = new Map<string, { country: string; city: string; lats: number[]; lngs: number[] }>();
  for (const r of restaurants) {
    const p = parseRegion(r.region);
    if (!p || !p.country || !p.city) continue;
    const key = `${p.country}|${p.city}`;
    if (!groups.has(key)) groups.set(key, { country: p.country, city: p.city, lats: [], lngs: [] });
    const g = groups.get(key)!;
    g.lats.push(r.latitude);
    g.lngs.push(r.longitude);
  }
  let best: { country: string; city: string } | null = null;
  let bestDist = Infinity;
  for (const g of groups.values()) {
    const cLat = g.lats.reduce((a, b) => a + b, 0) / g.lats.length;
    const cLng = g.lngs.reduce((a, b) => a + b, 0) / g.lngs.length;
    const dist = (cLat - lat) ** 2 + (cLng - lng) ** 2;
    if (dist < bestDist) {
      bestDist = dist;
      best = { country: g.country, city: g.city };
    }
  }
  return best;
}

export default function Home() {
  const { user, login, logout, isLoading: authLoading } = useAuth();
  const [restaurants, setRestaurants] = useState<Restaurant[]>([]);
  const [selected, setSelected] = useState<Restaurant | null>(null);
  const [loading, setLoading] = useState(true);
  const [showDetail, setShowDetail] = useState(false);
  const [channels, setChannels] = useState<Channel[]>([]);
  const [channelFilter, setChannelFilter] = useState("");
  const [cuisineFilter, setCuisineFilter] = useState("");
  const [priceFilter, setPriceFilter] = useState("");
  const [viewMode, setViewMode] = useState<"map" | "list">("list");
  const [mobileTab, setMobileTab] = useState<"home" | "list" | "nearby" | "favorites" | "profile">("home");
  const [showMobileFilters, setShowMobileFilters] = useState(false);
  const [mapBounds, setMapBounds] = useState<MapBounds | null>(null);
  const [boundsFilterOn, setBoundsFilterOn] = useState(false);
  const [countryFilter, setCountryFilter] = useState("");
  const [cityFilter, setCityFilter] = useState("");
  const [districtFilter, setDistrictFilter] = useState("");
  const [regionFlyTo, setRegionFlyTo] = useState<FlyTo | null>(null);
  const [showFavorites, setShowFavorites] = useState(false);
  const [showMyReviews, setShowMyReviews] = useState(false);
  const [myReviews, setMyReviews] = useState<(Review & { restaurant_id: string; restaurant_name: string | null })[]>([]);
  const [visits, setVisits] = useState<{ today: number; total: number } | null>(null);
  const [userLoc, setUserLoc] = useState<{ lat: number; lng: number }>({ lat: 37.498, lng: 127.0276 });
  const geoApplied = useRef(false);

  const regionTree = useMemo(() => buildRegionTree(restaurants), [restaurants]);
  const countries = useMemo(() => [...regionTree.keys()].sort(), [regionTree]);
  const cities = useMemo(() => {
    if (!countryFilter) return [];
    const cityMap = regionTree.get(countryFilter);
    return cityMap ? [...cityMap.keys()].sort() : [];
  }, [regionTree, countryFilter]);
  const districts = useMemo(() => {
    if (!countryFilter || !cityFilter) return [];
    const cityMap = regionTree.get(countryFilter);
    if (!cityMap) return [];
    const set = cityMap.get(cityFilter);
    return set ? [...set].sort() : [];
  }, [regionTree, countryFilter, cityFilter]);

  const filteredRestaurants = useMemo(() => {
    const dist = (r: Restaurant) =>
      (r.latitude - userLoc.lat) ** 2 + (r.longitude - userLoc.lng) ** 2;
    return restaurants.filter((r) => {
      if (channelFilter && !(r.channels || []).includes(channelFilter)) return false;
      if (cuisineFilter && !matchCuisineFilter(r.cuisine_type, cuisineFilter)) return false;
      if (priceFilter && !matchPriceGroup(r.price_range, priceFilter)) return false;
      if (countryFilter) {
        const parsed = parseRegion(r.region);
        if (!parsed || parsed.country !== countryFilter) return false;
        if (cityFilter && parsed.city !== cityFilter) return false;
        if (districtFilter && parsed.district !== districtFilter) return false;
      }
      if (boundsFilterOn && mapBounds) {
        if (r.latitude < mapBounds.south || r.latitude > mapBounds.north) return false;
        if (r.longitude < mapBounds.west || r.longitude > mapBounds.east) return false;
      }
      return true;
    }).sort((a, b) => {
      const da = dist(a), db = dist(b);
      if (da !== db) return da - db;
      return (b.rating || 0) - (a.rating || 0);
    });
  }, [restaurants, channelFilter, cuisineFilter, priceFilter, countryFilter, cityFilter, districtFilter, boundsFilterOn, mapBounds, userLoc]);

  // Set desktop default to map mode on mount + get user location
  useEffect(() => {
    if (window.innerWidth >= 768) setViewMode("map");
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        (pos) => setUserLoc({ lat: pos.coords.latitude, lng: pos.coords.longitude }),
        () => {},
        { timeout: 5000 },
      );
    }
  }, []);

  // Load channels + record visit on mount
  useEffect(() => {
    api.getChannels().then(setChannels).catch(console.error);
    api.recordVisit().then(() => api.getVisits().then(setVisits)).catch(console.error);
  }, []);

  // Load restaurants on mount and when channel filter changes
  useEffect(() => {
    setLoading(true);
    api
      .getRestaurants({ limit: 500, channel: channelFilter || undefined })
      .then(setRestaurants)
      .catch(console.error)
      .finally(() => setLoading(false));
  }, [channelFilter]);

  // Auto-select region from user's geolocation (once)
  useEffect(() => {
    if (geoApplied.current || restaurants.length === 0) return;
    if (!navigator.geolocation) return;
    navigator.geolocation.getCurrentPosition(
      (pos) => {
        if (geoApplied.current) return;
        geoApplied.current = true;
        const match = findRegionFromCoords(pos.coords.latitude, pos.coords.longitude, restaurants);
        if (match) {
          setCountryFilter(match.country);
          setCityFilter(match.city);
        }
        const mobile = window.innerWidth < 768;
        setRegionFlyTo({ lat: pos.coords.latitude, lng: pos.coords.longitude, zoom: mobile ? 13 : 16 });
      },
      () => { /* user denied or error — do nothing */ },
      { timeout: 5000 },
    );
  }, [restaurants]);

  const handleSearch = useCallback(
    async (query: string, mode: "keyword" | "semantic" | "hybrid") => {
      setLoading(true);
      try {
        const results = await api.search(query, mode);
        setRestaurants(results);
        setSelected(null);
        setShowDetail(false);
      } catch (e) {
        console.error("Search failed:", e);
      } finally {
        setLoading(false);
      }
    },
    []
  );

  const handleSelectRestaurant = useCallback((r: Restaurant) => {
    setSelected(r);
    setShowDetail(true);
  }, []);

  const handleCloseDetail = useCallback(() => {
    setShowDetail(false);
  }, []);

  const handleBoundsChanged = useCallback((bounds: MapBounds) => {
    setMapBounds(bounds);
  }, []);

  const handleMyLocation = useCallback(() => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        (pos) => {
          setUserLoc({ lat: pos.coords.latitude, lng: pos.coords.longitude });
          setRegionFlyTo({ lat: pos.coords.latitude, lng: pos.coords.longitude, zoom: 16 });
        },
        () => setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 16 }),
        { timeout: 5000 },
      );
    } else {
      setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 16 });
    }
  }, []);

  const handleCountryChange = useCallback((country: string) => {
    setCountryFilter(country);
    setCityFilter("");
    setDistrictFilter("");
    if (!country) { setRegionFlyTo(null); return; }
    const matched = restaurants.filter((r) => {
      const p = parseRegion(r.region);
      return p && p.country === country;
    });
    setRegionFlyTo(computeFlyTo(matched));
  }, [restaurants]);

  const handleCityChange = useCallback((city: string) => {
    setCityFilter(city);
    setDistrictFilter("");
    if (!city) {
      // Re-fly to country level
      const matched = restaurants.filter((r) => {
        const p = parseRegion(r.region);
        return p && p.country === countryFilter;
      });
      setRegionFlyTo(computeFlyTo(matched));
      return;
    }
    const matched = restaurants.filter((r) => {
      const p = parseRegion(r.region);
      return p && p.country === countryFilter && p.city === city;
    });
    setRegionFlyTo(computeFlyTo(matched));
  }, [restaurants, countryFilter]);

  const handleDistrictChange = useCallback((district: string) => {
    setDistrictFilter(district);
    if (!district) {
      const matched = restaurants.filter((r) => {
        const p = parseRegion(r.region);
        return p && p.country === countryFilter && p.city === cityFilter;
      });
      setRegionFlyTo(computeFlyTo(matched));
      return;
    }
    const matched = restaurants.filter((r) => {
      const p = parseRegion(r.region);
      return p && p.country === countryFilter && p.city === cityFilter && p.district === district;
    });
    setRegionFlyTo(computeFlyTo(matched));
  }, [restaurants, countryFilter, cityFilter]);

  const handleReset = useCallback(() => {
    setLoading(true);
    setChannelFilter("");
    setCuisineFilter("");
    setPriceFilter("");
    setCountryFilter("");
    setCityFilter("");
    setDistrictFilter("");
    setRegionFlyTo(null);
    setBoundsFilterOn(false);
    setShowFavorites(false);
    setShowMyReviews(false);
    api
      .getRestaurants({ limit: 500 })
      .then((data) => {
        setRestaurants(data);
        setSelected(null);
        setShowDetail(false);
      })
      .catch(console.error)
      .finally(() => setLoading(false));
  }, []);

  const handleMobileTab = useCallback(async (tab: "home" | "list" | "nearby" | "favorites" | "profile") => {
    // 홈 탭 재클릭 = 리셋
    if (tab === "home" && mobileTab === "home") {
      handleReset();
      return;
    }

    setMobileTab(tab);
    setShowDetail(false);
    setShowMobileFilters(false);
    setSelected(null);

    if (tab === "nearby") {
      setBoundsFilterOn(true);
      if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(
          (pos) => setRegionFlyTo({ lat: pos.coords.latitude, lng: pos.coords.longitude, zoom: 13 }),
          () => setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 13 }),
          { timeout: 5000 },
        );
      } else {
        setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 13 });
      }
      // 내주변에서 돌아올 때를 위해 favorites/reviews 해제
      if (showFavorites || showMyReviews) {
        setShowFavorites(false);
        setShowMyReviews(false);
        setMyReviews([]);
        api.getRestaurants({ limit: 500, channel: channelFilter || undefined }).then(setRestaurants);
      }
      return;
    }

    setBoundsFilterOn(false);

    if (tab === "favorites") {
      if (!user) return;
      setShowMyReviews(false);
      setMyReviews([]);
      try {
        const favs = await api.getMyFavorites();
        setRestaurants(favs);
        setShowFavorites(true);
      } catch { /* ignore */ }
    } else if (tab === "profile") {
      if (!user) return;
      setShowFavorites(false);
      try {
        const reviews = await api.getMyReviews();
        setMyReviews(reviews);
        setShowMyReviews(true);
      } catch { /* ignore */ }
      // 프로필에서는 식당 목록을 원래대로 복원
      if (showFavorites) {
        api.getRestaurants({ limit: 500, channel: channelFilter || undefined }).then(setRestaurants);
      }
    } else {
      // 홈 / 식당 목록 - 항상 전체 식당 목록으로 복원
      const needReload = showFavorites || showMyReviews;
      setShowFavorites(false);
      setShowMyReviews(false);
      setMyReviews([]);
      if (needReload) {
        const data = await api.getRestaurants({ limit: 500, channel: channelFilter || undefined });
        setRestaurants(data);
      }
    }
  }, [user, showFavorites, showMyReviews, channelFilter, mobileTab, handleReset]);

  const handleToggleFavorites = async () => {
    if (showFavorites) {
      setShowFavorites(false);
      const data = await api.getRestaurants({ limit: 500, channel: channelFilter || undefined });
      setRestaurants(data);
    } else {
      try {
        const favs = await api.getMyFavorites();
        setRestaurants(favs);
        setShowFavorites(true);
        setShowMyReviews(false);
        setMyReviews([]);
        setSelected(null);
        setShowDetail(false);
      } catch { /* ignore */ }
    }
  };

  const handleToggleMyReviews = async () => {
    if (showMyReviews) {
      setShowMyReviews(false);
      setMyReviews([]);
    } else {
      try {
        const reviews = await api.getMyReviews();
        setMyReviews(reviews);
        setShowMyReviews(true);
        setShowFavorites(false);
        setSelected(null);
        setShowDetail(false);
      } catch { /* ignore */ }
    }
  };

  // Desktop sidebar: shows detail inline
  const sidebarContent = showMyReviews ? (
    <MyReviewsList
      reviews={myReviews}
      onClose={() => { setShowMyReviews(false); setMyReviews([]); }}
      onSelectRestaurant={async (restaurantId) => {
        try {
          const r = await api.getRestaurant(restaurantId);
          handleSelectRestaurant(r);
          setShowMyReviews(false);
          setMyReviews([]);
        } catch { /* ignore */ }
      }}
    />
  ) : showDetail && selected ? (
    <RestaurantDetail
      restaurant={selected}
      onClose={handleCloseDetail}
    />
  ) : (
    <RestaurantList
      restaurants={filteredRestaurants}
      selectedId={selected?.id}
      onSelect={handleSelectRestaurant}
      loading={loading}
      keyPrefix="d-"
    />
  );

  // Mobile list: always shows list (detail goes to bottom sheet)
  const mobileListContent = showMyReviews ? (
    <MyReviewsList
      reviews={myReviews}
      onClose={() => { setShowMyReviews(false); setMyReviews([]); }}
      onSelectRestaurant={async (restaurantId) => {
        try {
          const r = await api.getRestaurant(restaurantId);
          handleSelectRestaurant(r);
          setShowMyReviews(false);
          setMyReviews([]);
        } catch { /* ignore */ }
      }}
    />
  ) : (
    <RestaurantList
      restaurants={filteredRestaurants}
      selectedId={selected?.id}
      onSelect={handleSelectRestaurant}
      loading={loading}
      keyPrefix="m-"
    />
  );

  return (
    <div className="h-screen flex flex-col bg-white dark:bg-gray-950">
      {/* ── Header row 1: Logo + User ── */}
      <header className="bg-white/80 dark:bg-gray-900/80 backdrop-blur-md border-b dark:border-gray-800 shrink-0">
        <div className="px-5 py-3 flex items-center justify-between">
          <button onClick={handleReset} className="text-lg font-bold whitespace-nowrap">
            Tasteby
          </button>

          {/* Desktop: search + filters — two rows */}
          <div className="hidden md:flex flex-col gap-2.5 mx-6">
            {/* Row 1: Search + dropdown filters */}
            <div className="flex items-center gap-3">
              <div className="w-96 shrink-0">
                <SearchBar onSearch={handleSearch} isLoading={loading} />
              </div>
              <button
                onClick={handleReset}
                className="p-1.5 text-gray-400 dark:text-gray-500 hover:text-orange-500 dark:hover:text-orange-400 transition-colors"
                title="초기화"
              >
                <svg viewBox="0 0 24 24" className="w-5 h-5 fill-current"><path d="M17.65 6.35A7.958 7.958 0 0012 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0112 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
              </button>
              <select
                value={channelFilter}
                onChange={(e) => {
                  setChannelFilter(e.target.value);
                  setSelected(null);
                  setShowDetail(false);
                }}
                className="border dark:border-gray-700 rounded-lg px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 dark:bg-gray-800"
              >
                <option value="">📺 채널</option>
                {channels.map((ch) => (
                  <option key={ch.id} value={ch.channel_name}>
                    📺 {ch.channel_name}
                  </option>
                ))}
              </select>
              <select
                value={cuisineFilter}
                onChange={(e) => setCuisineFilter(e.target.value)}
                className="border dark:border-gray-700 rounded-lg px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 dark:bg-gray-800"
              >
                <option value="">🍽 장르</option>
                {CUISINE_TAXONOMY.map((g) => (
                  <optgroup key={g.category} label={`── ${g.category} ──`}>
                    <option value={g.category}>🍽 {g.category} 전체</option>
                    {g.items.map((item) => (
                      <option key={`${g.category}|${item}`} value={`${g.category}|${item}`}>
                        &nbsp;&nbsp;{item}
                      </option>
                    ))}
                  </optgroup>
                ))}
              </select>
              <select
                value={priceFilter}
                onChange={(e) => setPriceFilter(e.target.value)}
                className="border dark:border-gray-700 rounded-lg px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 dark:bg-gray-800"
              >
                <option value="">💰 가격</option>
                {PRICE_GROUPS.map((g) => (
                  <option key={g.label} value={g.label}>{g.label}</option>
                ))}
              </select>
            </div>
            {/* Row 2: Region filters + Toggle buttons + count */}
            <div className="flex items-center gap-3">
              <select
                value={countryFilter}
                onChange={(e) => handleCountryChange(e.target.value)}
                className="border dark:border-gray-700 rounded-lg px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 dark:bg-gray-800"
              >
                <option value="">🌍 나라</option>
                {countries.map((c) => (
                  <option key={c} value={c}>🌍 {c}</option>
                ))}
              </select>
              {countryFilter && cities.length > 0 && (
                <select
                  value={cityFilter}
                  onChange={(e) => handleCityChange(e.target.value)}
                  className="border dark:border-gray-700 rounded-lg px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 dark:bg-gray-800"
                >
                  <option value="">🏙 전체 시/도</option>
                  {cities.map((c) => (
                    <option key={c} value={c}>🏙 {c}</option>
                  ))}
                </select>
              )}
              {cityFilter && districts.length > 0 && (
                <select
                  value={districtFilter}
                  onChange={(e) => handleDistrictChange(e.target.value)}
                  className="border dark:border-gray-700 rounded-lg px-3 py-1.5 text-sm text-gray-600 dark:text-gray-300 dark:bg-gray-800"
                >
                  <option value="">🏘 전체 구/군</option>
                  {districts.map((d) => (
                    <option key={d} value={d}>🏘 {d}</option>
                  ))}
                </select>
              )}
              <div className="w-px h-5 bg-gray-200 dark:bg-gray-700" />
              <button
                onClick={() => {
                  const next = !boundsFilterOn;
                  setBoundsFilterOn(next);
                  if (next) {
                    if (navigator.geolocation) {
                      navigator.geolocation.getCurrentPosition(
                        (pos) => setRegionFlyTo({ lat: pos.coords.latitude, lng: pos.coords.longitude, zoom: 15 }),
                        () => setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 15 }),
                        { timeout: 5000 },
                      );
                    } else {
                      setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 15 });
                    }
                  }
                }}
                className={`px-3 py-1.5 text-sm border rounded-lg transition-colors ${
                  boundsFilterOn
                    ? "bg-orange-50 dark:bg-orange-900/30 border-orange-300 dark:border-orange-700 text-orange-600 dark:text-orange-400"
                    : "hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-600 dark:text-gray-400"
                }`}
                title="내 위치 주변 식당만 표시"
              >
                {boundsFilterOn ? "📍 내위치 ON" : "📍 내위치"}
              </button>
              <button
                onClick={() => setViewMode(viewMode === "map" ? "list" : "map")}
                className="px-3 py-1.5 text-sm border rounded-lg transition-colors hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-600 dark:text-gray-400"
                title={viewMode === "map" ? "리스트 우선" : "지도 우선"}
              >
                {viewMode === "map" ? "🗺 지도" : "☰ 리스트"}
              </button>
              {user && (
                <>
                  <button
                    onClick={handleToggleFavorites}
                    className={`px-3.5 py-1.5 text-sm rounded-full border transition-colors ${
                      showFavorites
                        ? "bg-rose-50 dark:bg-rose-900/30 border-rose-300 dark:border-rose-700 text-rose-600 dark:text-rose-400"
                        : "border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-100"
                    }`}
                  >
                    {showFavorites ? "♥ 내 찜" : "♡ 찜"}
                  </button>
                  <button
                    onClick={handleToggleMyReviews}
                    className={`px-3.5 py-1.5 text-sm rounded-full border transition-colors ${
                      showMyReviews
                        ? "bg-orange-50 dark:bg-orange-900/30 border-orange-300 dark:border-orange-700 text-orange-600 dark:text-orange-400"
                        : "border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-100"
                    }`}
                  >
                    {showMyReviews ? "✎ 내 리뷰" : "✎ 리뷰"}
                  </button>
                </>
              )}
              <span className="text-sm text-gray-500 whitespace-nowrap">
                {filteredRestaurants.length}개
              </span>
            </div>
          </div>

          {/* User area */}
          <div className="shrink-0 flex items-center gap-3 ml-auto">
            {authLoading ? null : user ? (
              <div className="flex items-center gap-2">
                {user.avatar_url ? (
                  <img
                    src={user.avatar_url}
                    alt=""
                    className="w-8 h-8 rounded-full border border-gray-200"
                  />
                ) : (
                  <div className="w-8 h-8 rounded-full bg-orange-100 text-orange-700 flex items-center justify-center text-sm font-semibold border border-orange-200">
                    {(user.nickname || user.email || "?").charAt(0).toUpperCase()}
                  </div>
                )}
                <span className="hidden sm:inline text-sm font-medium text-gray-700 dark:text-gray-300">
                  {user.nickname || user.email}
                </span>
                <button
                  onClick={logout}
                  className="ml-1 px-2.5 py-1 text-xs text-gray-500 dark:text-gray-400 border border-gray-300 dark:border-gray-700 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-200 transition-colors"
                >
                  로그아웃
                </button>
              </div>
            ) : (
              <LoginMenu onGoogleSuccess={(credential) => login(credential).catch(console.error)} />
            )}
          </div>
        </div>

        {/* ── Header row 2 (mobile only): search + toolbar ── */}
        <div className={`md:hidden px-4 pb-3 space-y-2 ${mobileTab === "favorites" || mobileTab === "profile" ? "hidden" : ""}`}>
          {/* Row 1: Search */}
          <SearchBar onSearch={handleSearch} isLoading={loading} />
          {/* Row 2: Toolbar */}
          <div className="flex items-center gap-2">
            <button
              onClick={() => setShowMobileFilters(!showMobileFilters)}
              className={`px-3 py-1.5 text-xs border rounded-lg transition-colors relative ${
                showMobileFilters || channelFilter || cuisineFilter || priceFilter || countryFilter
                  ? "bg-orange-50 dark:bg-orange-900/30 border-orange-300 dark:border-orange-700 text-orange-600 dark:text-orange-400"
                  : "text-gray-600"
              }`}
            >
              {showMobileFilters ? "✕ 닫기" : "🔽 필터"}
              {!showMobileFilters && (channelFilter || cuisineFilter || priceFilter || countryFilter) && (
                <span className="absolute -top-1.5 -right-1.5 w-4 h-4 bg-orange-500 text-white rounded-full text-[9px] flex items-center justify-center">
                  {[channelFilter, cuisineFilter, priceFilter, countryFilter].filter(Boolean).length}
                </span>
              )}
            </button>
            <span className="text-xs text-gray-400 ml-auto">
              {filteredRestaurants.length}개
            </span>
          </div>

          {/* Collapsible filter panel */}
          {showMobileFilters && (
            <div className="bg-white/70 dark:bg-gray-900/70 backdrop-blur-md rounded-xl p-3.5 space-y-3 border border-white/50 dark:border-gray-700/50 shadow-sm">
              {/* Dropdown filters */}
              <div className="flex items-center gap-2 flex-wrap">
                <select
                  value={channelFilter}
                  onChange={(e) => {
                    setChannelFilter(e.target.value);
                    setSelected(null);
                    setShowDetail(false);
                  }}
                  className="border dark:border-gray-700 rounded-lg px-2.5 py-1.5 text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"
                >
                  <option value="">📺 채널</option>
                  {channels.map((ch) => (
                    <option key={ch.id} value={ch.channel_name}>
                      📺 {ch.channel_name}
                    </option>
                  ))}
                </select>
                <select
                  value={cuisineFilter}
                  onChange={(e) => setCuisineFilter(e.target.value)}
                  className="border dark:border-gray-700 rounded-lg px-2.5 py-1.5 text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"
                >
                  <option value="">🍽 장르</option>
                  {CUISINE_TAXONOMY.map((g) => (
                    <optgroup key={g.category} label={`── ${g.category} ──`}>
                      <option value={g.category}>🍽 {g.category} 전체</option>
                      {g.items.map((item) => (
                        <option key={`${g.category}|${item}`} value={`${g.category}|${item}`}>
                          &nbsp;&nbsp;{item}
                        </option>
                      ))}
                    </optgroup>
                  ))}
                </select>
                <select
                  value={priceFilter}
                  onChange={(e) => setPriceFilter(e.target.value)}
                  className="border dark:border-gray-700 rounded-lg px-2.5 py-1.5 text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"
                >
                  <option value="">💰 가격</option>
                  {PRICE_GROUPS.map((g) => (
                    <option key={g.label} value={g.label}>💰 {g.label}</option>
                  ))}
                </select>
              </div>
              {/* Region filters */}
              <div className="flex items-center gap-2 flex-wrap">
                <select
                  value={countryFilter}
                  onChange={(e) => handleCountryChange(e.target.value)}
                  className="border dark:border-gray-700 rounded-lg px-2.5 py-1.5 text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"
                >
                  <option value="">🌍 나라</option>
                  {countries.map((c) => (
                    <option key={c} value={c}>🌍 {c}</option>
                  ))}
                </select>
                {countryFilter && cities.length > 0 && (
                  <select
                    value={cityFilter}
                    onChange={(e) => handleCityChange(e.target.value)}
                    className="border dark:border-gray-700 rounded-lg px-2.5 py-1.5 text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"
                  >
                    <option value="">🏙 전체 시/도</option>
                    {cities.map((c) => (
                      <option key={c} value={c}>🏙 {c}</option>
                    ))}
                  </select>
                )}
                {cityFilter && districts.length > 0 && (
                  <select
                    value={districtFilter}
                    onChange={(e) => handleDistrictChange(e.target.value)}
                    className="border dark:border-gray-700 rounded-lg px-2.5 py-1.5 text-xs text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"
                  >
                    <option value="">🏘 전체 구/군</option>
                    {districts.map((d) => (
                      <option key={d} value={d}>🏘 {d}</option>
                    ))}
                  </select>
                )}
              </div>
              {/* Toggle buttons */}
              <div className="flex items-center gap-2 flex-wrap">
                <button
                  onClick={() => {
                    const next = !boundsFilterOn;
                    setBoundsFilterOn(next);
                    if (next) {
                      if (navigator.geolocation) {
                        navigator.geolocation.getCurrentPosition(
                          (pos) => setRegionFlyTo({ lat: pos.coords.latitude, lng: pos.coords.longitude, zoom: 15 }),
                          () => setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 15 }),
                          { timeout: 5000 },
                        );
                      } else {
                        setRegionFlyTo({ lat: 37.498, lng: 127.0276, zoom: 15 });
                      }
                    }
                  }}
                  className={`px-2.5 py-1.5 text-xs border rounded-lg transition-colors ${
                    boundsFilterOn
                      ? "bg-orange-50 dark:bg-orange-900/30 border-orange-300 dark:border-orange-700 text-orange-600 dark:text-orange-400"
                      : "text-gray-600 dark:text-gray-400 bg-white dark:bg-gray-800"
                  }`}
                >
                  {boundsFilterOn ? "📍 내위치 ON" : "📍 내위치"}
                </button>
              </div>
            </div>
          )}
        </div>
      </header>

      {/* ── Body: Desktop = side-by-side, Mobile = stacked ── */}

      {/* Desktop layout */}
      <div className="hidden md:flex flex-1 overflow-hidden">
        {viewMode === "map" ? (
          <>
            <aside className="w-80 bg-white dark:bg-gray-950 border-r dark:border-gray-800 overflow-y-auto shrink-0">
              {sidebarContent}
            </aside>
            <main className="flex-1 relative">
              <MapView
                restaurants={filteredRestaurants}
                selected={selected}
                onSelectRestaurant={handleSelectRestaurant}
                onBoundsChanged={handleBoundsChanged}
                flyTo={regionFlyTo}
                onMyLocation={handleMyLocation}
                activeChannel={channelFilter || undefined}
              />
              {visits && (
                <div className="absolute bottom-1 right-2 bg-white/60 backdrop-blur-sm text-gray-700 text-[10px] px-2.5 py-1 rounded-lg shadow-sm">
                  오늘 {visits.today} · 전체 {visits.total.toLocaleString()}
                </div>
              )}
            </main>
          </>
        ) : (
          <>
            <aside className="flex-1 bg-white dark:bg-gray-950 overflow-y-auto">
              {sidebarContent}
            </aside>
            <main className="w-[40%] shrink-0 relative border-l dark:border-gray-800">
              <MapView
                restaurants={filteredRestaurants}
                selected={selected}
                onSelectRestaurant={handleSelectRestaurant}
                onBoundsChanged={handleBoundsChanged}
                flyTo={regionFlyTo}
                onMyLocation={handleMyLocation}
                activeChannel={channelFilter || undefined}
              />
              {visits && (
                <div className="absolute bottom-1 right-2 bg-white/60 backdrop-blur-sm text-gray-700 text-[10px] px-2.5 py-1 rounded-lg shadow-sm">
                  오늘 {visits.today} · 전체 {visits.total.toLocaleString()}
                </div>
              )}
            </main>
          </>
        )}
      </div>

      {/* Mobile layout */}
      <div className="md:hidden flex-1 flex flex-col overflow-hidden pb-14">
        {/* Tab content — takes all remaining space above fixed nav */}
        {mobileTab === "nearby" ? (
          /* 내주변: 지도 + 리스트 분할, 영역필터 ON */
          <div className="flex-1 flex flex-col overflow-hidden">
            <div className="h-[45%] relative shrink-0">
              <MapView
                restaurants={filteredRestaurants}
                selected={selected}
                onSelectRestaurant={handleSelectRestaurant}
                onBoundsChanged={handleBoundsChanged}
                flyTo={regionFlyTo}
                onMyLocation={handleMyLocation}
                activeChannel={channelFilter || undefined}
              />
              <div className="absolute top-2 left-2 bg-white/90 dark:bg-gray-900/90 backdrop-blur-sm rounded-lg px-3 py-1.5 shadow-sm z-10">
                <span className="text-xs font-medium text-orange-600 dark:text-orange-400">
                  내 주변 {filteredRestaurants.length}개
                </span>
              </div>
              {visits && (
                <div className="absolute bottom-1 right-2 bg-white/60 backdrop-blur-sm text-gray-700 text-[10px] px-2.5 py-1 rounded-lg shadow-sm z-10">
                  오늘 {visits.today} · 전체 {visits.total.toLocaleString()}
                </div>
              )}
            </div>
            <div className="flex-1 overflow-y-auto">
              {mobileListContent}
            </div>
          </div>
        ) : mobileTab === "profile" ? (
          /* 내정보 */
          <div className="flex-1 overflow-y-auto bg-white dark:bg-gray-950">
            {!user ? (
              <div className="flex flex-col items-center justify-center h-full gap-4 px-6">
                <p className="text-gray-500 dark:text-gray-400 text-sm">로그인하고 리뷰와 찜 목록을 관리하세요</p>
                <GoogleLogin
                  onSuccess={(res) => {
                    if (res.credential) login(res.credential).catch(console.error);
                  }}
                  onError={() => console.error("Google login failed")}
                  size="large"
                  text="signin_with"
                />
              </div>
            ) : (
              <div className="p-4 space-y-4">
                {/* 프로필 헤더 */}
                <div className="flex items-center gap-3 pb-4 border-b dark:border-gray-800">
                  {user.avatar_url ? (
                    <img src={user.avatar_url} alt="" className="w-12 h-12 rounded-full border border-gray-200" />
                  ) : (
                    <div className="w-12 h-12 rounded-full bg-orange-100 text-orange-700 flex items-center justify-center text-lg font-semibold border border-orange-200">
                      {(user.nickname || user.email || "?").charAt(0).toUpperCase()}
                    </div>
                  )}
                  <div className="flex-1">
                    <p className="font-semibold text-sm dark:text-gray-100">{user.nickname || user.email}</p>
                    {user.nickname && user.email && (
                      <p className="text-xs text-gray-400">{user.email}</p>
                    )}
                  </div>
                  <button
                    onClick={logout}
                    className="px-3 py-1.5 text-xs text-gray-500 border border-gray-300 dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800"
                  >
                    로그아웃
                  </button>
                </div>
                {/* 내 리뷰 */}
                <div>
                  <h3 className="font-semibold text-sm mb-2 dark:text-gray-200">내 리뷰</h3>
                  {myReviews.length === 0 ? (
                    <p className="text-sm text-gray-400">작성한 리뷰가 없습니다</p>
                  ) : (
                    <MyReviewsList
                      reviews={myReviews}
                      onClose={() => {}}
                      onSelectRestaurant={async (restaurantId) => {
                        try {
                          const r = await api.getRestaurant(restaurantId);
                          handleSelectRestaurant(r);
                        } catch { /* ignore */ }
                      }}
                    />
                  )}
                </div>
              </div>
            )}
          </div>
        ) : (
          /* 홈 / 식당 목록 / 찜: 리스트 표시 */
          <div className="flex-1 overflow-y-auto bg-white dark:bg-gray-950">
            {mobileTab === "favorites" && !user ? (
              <div className="flex flex-col items-center justify-center h-full gap-4 px-6">
                <p className="text-gray-500 dark:text-gray-400 text-sm">로그인하고 찜 목록을 확인하세요</p>
                <GoogleLogin
                  onSuccess={(res) => {
                    if (res.credential) login(res.credential).catch(console.error);
                  }}
                  onError={() => console.error("Google login failed")}
                  size="large"
                  text="signin_with"
                />
              </div>
            ) : (
              mobileListContent
            )}
          </div>
        )}

        {/* Mobile Bottom Sheet for restaurant detail */}
        <BottomSheet open={showDetail && !!selected} onClose={handleCloseDetail}>
          {selected && (
            <RestaurantDetail restaurant={selected} onClose={handleCloseDetail} />
          )}
        </BottomSheet>
      </div>

      {/* ── Mobile Bottom Nav (fixed) ── */}
      <nav className="md:hidden fixed bottom-0 left-0 right-0 z-40 border-t dark:border-gray-800 bg-white dark:bg-gray-950 safe-area-bottom">
        <div className="flex items-stretch h-14">
            {([
              { key: "home", label: "홈", icon: (
                <svg viewBox="0 0 24 24" className="w-5 h-5 fill-current"><path d="M12 3l9 8h-3v9h-5v-6h-2v6H6v-9H3z"/></svg>
              )},
              { key: "list", label: "식당 목록", icon: (
                <svg viewBox="0 0 24 24" className="w-5 h-5 fill-current"><path d="M3 4h18v2H3zm0 7h18v2H3zm0 7h18v2H3z"/></svg>
              )},
              { key: "nearby", label: "내주변", icon: (
                <svg viewBox="0 0 24 24" className="w-5 h-5 fill-current"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
              )},
              { key: "favorites", label: "찜", icon: (
                <svg viewBox="0 0 24 24" className="w-5 h-5 fill-current"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></svg>
              )},
              { key: "profile", label: "내정보", icon: (
                <svg viewBox="0 0 24 24" className="w-5 h-5 fill-current"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>
              )},
            ] as { key: "home" | "list" | "nearby" | "favorites" | "profile"; label: string; icon: React.ReactNode }[]).map((tab) => (
              <button
                key={tab.key}
                onClick={() => handleMobileTab(tab.key)}
                className={`flex-1 flex flex-col items-center justify-center gap-0.5 py-2 transition-colors ${
                  mobileTab === tab.key
                    ? "text-orange-600 dark:text-orange-400"
                    : "text-gray-400 dark:text-gray-500"
                }`}
              >
                {tab.icon}
                <span className="text-[10px] font-medium">{tab.label}</span>
              </button>
            ))}
          </div>
        </nav>

      {/* Desktop Footer */}
      <footer className="hidden md:flex shrink-0 border-t dark:border-gray-800 bg-white/60 dark:bg-gray-900/60 backdrop-blur-sm py-2.5 items-center justify-center gap-2 text-[11px] text-gray-400 dark:text-gray-500 group">
        <div className="relative">
          <img
            src="/icon.jpg"
            alt="SDJ Labs"
            className="w-6 h-6 rounded-full border-2 border-orange-200 shadow-sm group-hover:scale-110 group-hover:rotate-12 transition-all duration-300"
          />
          <span className="absolute -top-0.5 -right-0.5 w-2 h-2 bg-orange-300 rounded-full animate-ping opacity-75" />
          <span className="absolute -top-0.5 -right-0.5 w-2 h-2 bg-orange-400 rounded-full" />
        </div>
        <span className="font-medium tracking-wide group-hover:text-gray-600 transition-colors">
          SDJ Labs Co., Ltd.
        </span>
      </footer>
    </div>
  );
}
