'use client';

import { useState, useRef, useEffect } from 'react';
import axios from 'axios';
import { useAuthStore } from '@/store/authStore';
import { type Country, SCRAPING_COUNTRIES } from '@/lib/countries';
import { services as SUPPORTED_SERVICES } from '@/components/SupportedServicesSection';
import { useTranslations } from 'next-intl';

const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';


const CURRENCIES = [
  { code: 'EUR', symbol: '€', name: 'Euro' },
  { code: 'USD', symbol: '$', name: 'US Dollar' },
  { code: 'GBP', symbol: '£', name: 'British Pound' },
  { code: 'CHF', symbol: 'CHF', name: 'Swiss Franc' },
  { code: 'JPY', symbol: '¥', name: 'Japanese Yen' },
  { code: 'AUD', symbol: 'A$', name: 'Australian Dollar' },
  { code: 'CAD', symbol: 'C$', name: 'Canadian Dollar' },
  { code: 'SEK', symbol: 'kr', name: 'Swedish Krona' },
  { code: 'NOK', symbol: 'kr', name: 'Norwegian Krone' },
  { code: 'DKK', symbol: 'kr', name: 'Danish Krone' },
  { code: 'PLN', symbol: 'zł', name: 'Polish Zloty' },
  { code: 'CZK', symbol: 'Kč', name: 'Czech Koruna' },
  { code: 'HUF', symbol: 'Ft', name: 'Hungarian Forint' },
  { code: 'RON', symbol: 'lei', name: 'Romanian Leu' },
  { code: 'BGN', symbol: 'лв', name: 'Bulgarian Lev' },
  { code: 'TRY', symbol: '₺', name: 'Turkish Lira' },
  { code: 'RUB', symbol: '₽', name: 'Russian Ruble' },
  { code: 'INR', symbol: '₹', name: 'Indian Rupee' },
  { code: 'CNY', symbol: '¥', name: 'Chinese Yuan' },
  { code: 'KRW', symbol: '₩', name: 'South Korean Won' },
  { code: 'BRL', symbol: 'R$', name: 'Brazilian Real' },
  { code: 'MXN', symbol: 'MX$', name: 'Mexican Peso' },
  { code: 'ZAR', symbol: 'R', name: 'South African Rand' },
  { code: 'AED', symbol: 'د.إ', name: 'UAE Dirham' },
  { code: 'THB', symbol: '฿', name: 'Thai Baht' },
  { code: 'MKD', symbol: 'ден', name: 'Macedonian Denar' },
  { code: 'RSD', symbol: 'дин', name: 'Serbian Dinar' },
];

export interface ScrapeResult {
  slotId: number;
  url: string;
  country: Country;
  loading: boolean;
  error: string | null;
  data: {
    provider?: string;
    desktop: { price: string; currency: string; description?: string };
    mobile: { price: string; currency: string; description?: string };
    reserveUrl?: string;
  } | null;
  /** Present only for unauthenticated preview results */
  teaser?: { hasGap: boolean };
  /** Present when the user's monthly search limit is reached */
  limitReached?: { plan: string; limit: number };
  /** Auto mode only: the highest desktop price found across all searched countries, used for the savings countdown animation */
  highestResult?: { price: string; currency: string };
  /** Auto mode only: live per-country checking progress shown while loading */
  checkingProgress?: { country: Country; done: boolean }[];
}

interface SearchSlot {
  id: number;
  url: string;
}

interface Props {
  onResults: React.Dispatch<React.SetStateAction<ScrapeResult[]>>;
  results: ScrapeResult[];
  compact?: boolean;
}

// Countries searched in auto mode
const AUTO_PRIMARY_CODES = ['IND', 'IDN', 'TUR', 'BRA', 'ARG', 'SRB', 'ALB'];
const AUTO_FALLBACK_CODES = ['THA', 'VNM', 'MEX', 'MYS'];

// Popular countries shown in the checking-progress display only (not actually searched)
const DISPLAY_POOL_CODES = [
  'USA', 'GBR', 'FRA', 'DEU', 'NOR', 'NLD', 'SWE', 'ITA', 'ESP',
  'AUS', 'CAN', 'JPN', 'ARE', 'SGP', 'CHE', 'AUT', 'BEL', 'DNK', 'FIN', 'NZL',
];

function pickRandom<T>(arr: T[], n: number): T[] {
  return [...arr].sort(() => Math.random() - 0.5).slice(0, n);
}

function parsePrice(price: string | undefined): number {
  if (!price || price === 'N/A') return Infinity;
  const num = parseFloat(price.replace(/[^0-9.]/g, ''));
  return isNaN(num) ? Infinity : num;
}

let slotIdCounter = 1;

export default function SearchSection({ onResults, results: _results, compact }: Props) {
  const { token, isAuthenticated, user } = useAuthStore();
  const t = useTranslations('search');
  const tc = useTranslations('common');
  const plan = user?.plan ?? 'free';
  const maxCountries = (plan === 'premium' || plan === 'max' || plan === 'business') ? 3 : 1;
  const defaultCountry = SCRAPING_COUNTRIES.find(c => c.code === 'USA') || SCRAPING_COUNTRIES[0];

  const [slots, setSlots] = useState<SearchSlot[]>([{ id: slotIdCounter++, url: '' }]);
  const [selectedCountries, setSelectedCountries] = useState<Country[]>([defaultCountry]);
  const [selectedCurrency, setSelectedCurrency] = useState(CURRENCIES[0]);
  const [includeMobile, setIncludeMobile] = useState(false);
  const [manualMode, setManualMode] = useState(false);
  const [showCountryPicker, setShowCountryPicker] = useState(false);
  const [showCurrencyPicker, setShowCurrencyPicker] = useState(false);
  const [countrySearch, setCountrySearch] = useState('');
  const [showPlatformsModal, setShowPlatformsModal] = useState(false);
  const countryPickerRef = useRef<HTMLDivElement>(null);
  const decoyTimerIdsRef = useRef<ReturnType<typeof setTimeout>[]>([]);
  const currencyRef = useRef<HTMLDivElement>(null);

  const filteredCountries = SCRAPING_COUNTRIES.filter(c =>
    c.name.toLowerCase().includes(countrySearch.toLowerCase()) ||
    c.code.toLowerCase().includes(countrySearch.toLowerCase())
  );

  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      if (countryPickerRef.current && !countryPickerRef.current.contains(e.target as Node)) {
        setShowCountryPicker(false);
        setCountrySearch('');
      }
      if (currencyRef.current && !currencyRef.current.contains(e.target as Node)) {
        setShowCurrencyPicker(false);
      }
    }
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  function addSlot() {
    if (slots.length < 6) {
      setSlots(prev => [...prev, { id: slotIdCounter++, url: '' }]);
    }
  }

  function updateUrl(id: number, url: string) {
    setSlots(prev => prev.map(s => s.id === id ? { ...s, url } : s));
  }

  function removeSlot(id: number) {
    if (slots.length > 1) {
      setSlots(prev => prev.filter(s => s.id !== id));
      onResults(prev => prev.filter(r => r.slotId !== id));
    }
  }

  function toggleCountry(country: Country) {
    if (maxCountries === 1) {
      // Single-country plans: clicking replaces the selection
      setSelectedCountries([country]);
      setShowCountryPicker(false);
      setCountrySearch('');
      return;
    }
    setSelectedCountries(prev => {
      const exists = prev.find(c => c.code === country.code);
      if (exists) {
        if (prev.length === 1) return prev; // keep at least one
        return prev.filter(c => c.code !== country.code);
      }
      if (prev.length >= maxCountries) return prev;
      return [...prev, country];
    });
  }

  function isShareLink(url: string): boolean {
    try {
      const { hostname, pathname } = new URL(url);
      return hostname.includes('booking.com') && pathname.startsWith('/Share-');
    } catch {
      return false;
    }
  }

  async function resolveShareLink(url: string): Promise<string> {
    const res = await axios.get(`${API_URL}/api/proxy/resolve-url`, {
      params: { url },
      headers: token ? { Authorization: `Bearer ${token}` } : {},
    });
    return res.data.url as string;
  }

  const autoCountries = (codes: string[]) =>
    codes.map(code => SCRAPING_COUNTRIES.find(c => c.code === code)).filter((c): c is Country => !!c);

  async function searchSlot(slot: SearchSlot) {
    if (!slot.url.trim()) return;

    let resolvedUrl = slot.url.trim();
    if (isShareLink(resolvedUrl)) {
      try {
        resolvedUrl = await resolveShareLink(resolvedUrl);
        setSlots(prev => prev.map(s => s.id === slot.id ? { ...s, url: resolvedUrl } : s));
      } catch {
        // proceed with original URL if resolution fails
      }
    }

    const placeholder: Country = { code: '__auto__', name: 'Searching…', flag: '⏳' };

    const fetchCountry = async (country: Country): Promise<ScrapeResult> => {
      try {
        const response = await axios.post(`${API_URL}/api/proxy/scrape-price`, {
          url: resolvedUrl, geo: country.name, currency: selectedCurrency.code, includeMobile,
        }, { headers: token ? { Authorization: `Bearer ${token}` } : {} });
        return { slotId: slot.id, url: resolvedUrl, country, loading: false, error: null, data: response.data };
      } catch (err: unknown) {
        if (axios.isAxiosError(err) && err.response?.status === 429 && err.response.data?.limitReached) {
          const { plan, limit } = err.response.data;
          return { slotId: slot.id, url: resolvedUrl, country, loading: false, error: null, data: null, limitReached: { plan, limit } };
        }
        const message = err instanceof Error ? err.message : 'Search failed';
        return { slotId: slot.id, url: resolvedUrl, country, loading: false, error: message, data: null };
      }
    };

    if (!isAuthenticated) {
      // UNAUTHENTICATED: show world map animation with DEU + SRB + decoy countries, then teaser
      const germany = SCRAPING_COUNTRIES.find(c => c.code === 'DEU')!;
      const serbia = SCRAPING_COUNTRIES.find(c => c.code === 'SRB')!;

      // Clear any leftover decoy timers
      decoyTimerIdsRef.current.forEach(clearTimeout);
      decoyTimerIdsRef.current = [];

      // Pick ~10 random display-only decoy countries (excluding DEU and SRB)
      const poolCountries = DISPLAY_POOL_CODES
        .filter(code => code !== 'DEU' && code !== 'SRB')
        .map(code => SCRAPING_COUNTRIES.find(c => c.code === code))
        .filter((c): c is Country => !!c);
      const decoyCountries = pickRandom(poolCountries, 10);

      const allProgress = [
        { country: germany, done: false },
        { country: serbia, done: false },
        ...decoyCountries.map(c => ({ country: c, done: false })),
      ].sort(() => Math.random() - 0.5);

      // Show loading card with checkingProgress so the world map renders
      onResults(prev => [
        ...prev.filter(r => r.slotId !== slot.id),
        {
          slotId: slot.id, url: resolvedUrl, country: placeholder,
          loading: true, error: null, data: null,
          checkingProgress: allProgress,
        },
      ]);

      const markProgress = (code: string) => {
        onResults(prev => prev.map(r =>
          r.slotId === slot.id && r.checkingProgress
            ? { ...r, checkingProgress: r.checkingProgress.map(cp => cp.country.code === code ? { ...cp, done: true } : cp) }
            : r
        ));
      };

      // Schedule decoy countries to appear "checked" at random times within 3s
      decoyTimerIdsRef.current = decoyCountries.map(decoy =>
        setTimeout(() => markProgress(decoy.code), Math.random() * 3000)
      );

      // Fetch real countries in parallel, mark done as each finishes
      const [deResult, srResult] = await Promise.all([
        fetchCountry(germany).then(r => { markProgress(germany.code); return r; }),
        fetchCountry(serbia).then(r => { markProgress(serbia.code); return r; }),
      ]);

      // Flush all remaining items to done so the map goes fully purple
      onResults(prev => prev.map(r =>
        r.slotId === slot.id && r.checkingProgress
          ? { ...r, checkingProgress: r.checkingProgress.map(cp => ({ ...cp, done: true })) }
          : r
      ));
      // Wait for the 0.5s fill transition + small buffer
      await new Promise<void>(resolve => setTimeout(resolve, 700));

      const dePrice = parsePrice(deResult.data?.desktop?.price);
      const srPrice = parsePrice(srResult.data?.desktop?.price);
      const hasGap = dePrice !== Infinity && srPrice !== Infinity && Math.abs(dePrice - srPrice) > 0.01;

      onResults(prev => [
        ...prev.filter(r => r.slotId !== slot.id),
        { slotId: slot.id, url: resolvedUrl, country: placeholder, loading: false, error: null, data: null, teaser: { hasGap } },
      ]);
      return;
    }

    if (!manualMode) {
      // AUTO MODE: show live per-country progress, then emit only the cheapest result
      const primary = autoCountries(AUTO_PRIMARY_CODES);

      // Clear any leftover decoy timers from a previous search
      decoyTimerIdsRef.current.forEach(clearTimeout);
      decoyTimerIdsRef.current = [];

      // Pick 14 random popular display-only countries and mix with real ones, shuffled
      const poolCountries = DISPLAY_POOL_CODES
        .map(code => SCRAPING_COUNTRIES.find(c => c.code === code))
        .filter((c): c is Country => !!c);
      const decoyCountries = pickRandom(poolCountries, 14);
      const allProgress = [
        ...primary.map(c => ({ country: c, done: false })),
        ...decoyCountries.map(c => ({ country: c, done: false })),
      ].sort(() => Math.random() - 0.5);

      // Show loading card with all countries (real + decoy) pending
      onResults(prev => [
        ...prev.filter(r => r.slotId !== slot.id),
        {
          slotId: slot.id, url: resolvedUrl, country: placeholder,
          loading: true, error: null, data: null,
          checkingProgress: allProgress,
        },
      ]);

      // Mark a country as done in the progress list
      const markDone = (code: string) => {
        onResults(prev => prev.map(r =>
          r.slotId === slot.id && r.checkingProgress
            ? { ...r, checkingProgress: r.checkingProgress.map(cp => cp.country.code === code ? { ...cp, done: true } : cp) }
            : r
        ));
      };

      // Schedule decoy countries to appear "checked" at random times within 3s
      decoyTimerIdsRef.current = decoyCountries.map(decoy =>
        setTimeout(() => markDone(decoy.code), Math.random() * 3000)
      );

      // Fetch first country alone to detect rate-limit before launching the rest
      const firstResult = await fetchCountry(primary[0]);
      markDone(primary[0].code);
      if (firstResult.limitReached) {
        onResults(prev => [
          ...prev.filter(r => r.slotId !== slot.id),
          firstResult,
        ]);
        return;
      }

      // Fetch remaining primary countries in parallel, updating progress as each finishes
      const remainingResults = await Promise.all(
        primary.slice(1).map(async country => {
          const result = await fetchCountry(country);
          markDone(country.code);
          return result;
        })
      );
      let all = [firstResult, ...remainingResults];

      // If all valid prices are identical, also search fallback countries
      const validPrices = all
        .filter(r => r.data?.desktop?.price && r.data.desktop.price !== 'N/A')
        .map(r => r.data!.desktop.price);
      if (validPrices.length > 0 && validPrices.every(p => p === validPrices[0])) {
        const fallback = autoCountries(AUTO_FALLBACK_CODES);
        // Append fallback countries to progress list
        onResults(prev => prev.map(r =>
          r.slotId === slot.id && r.checkingProgress
            ? { ...r, checkingProgress: [...r.checkingProgress, ...fallback.map(c => ({ country: c, done: false }))] }
            : r
        ));
        const fallbackResults = await Promise.all(
          fallback.map(async country => {
            const result = await fetchCountry(country);
            markDone(country.code);
            return result;
          })
        );
        all = [...all, ...fallbackResults];
      }

      // Pick the single cheapest result
      const withPrices = all.filter(r => r.data?.desktop?.price && r.data.desktop.price !== 'N/A');
      const best = withPrices.length > 0
        ? withPrices.reduce((a, b) => parsePrice(a.data!.desktop.price) <= parsePrice(b.data!.desktop.price) ? a : b)
        : (all.find(r => r.error) ?? all[0]);

      // Find the highest price for the savings countdown animation
      const worst = withPrices.length > 1
        ? withPrices.reduce((a, b) =>
            parsePrice(a.data!.desktop.price) >= parsePrice(b.data!.desktop.price) ? a : b
          )
        : null;
      const bestPrice = best ? parsePrice(best.data?.desktop.price) : Infinity;
      const worstPrice = worst ? parsePrice(worst.data!.desktop.price) : Infinity;
      const highestResult =
        worst && worstPrice > bestPrice + 0.01
          ? { price: worst.data!.desktop.price, currency: worst.data!.desktop.currency }
          : undefined;

      // Flush all remaining progress items to done=true so the world map
      // finishes its gray→purple transition before the result card appears
      onResults(prev => prev.map(r =>
        r.slotId === slot.id && r.checkingProgress
          ? { ...r, checkingProgress: r.checkingProgress.map(cp => ({ ...cp, done: true })) }
          : r
      ));
      // Wait for the 0.5s fill transition + small buffer
      await new Promise<void>(resolve => setTimeout(resolve, 700));

      onResults(prev => [
        ...prev.filter(r => r.slotId !== slot.id),
        ...(best ? [{ ...best, highestResult }] : []),
      ]);
      return;
    }

    // MANUAL MODE: search selected countries, stream results as they arrive
    onResults(prev => [
      ...prev.filter(r => r.slotId !== slot.id),
      ...selectedCountries.map(country => ({
        slotId: slot.id, url: resolvedUrl, country, loading: true, error: null, data: null,
      })),
    ]);

    await Promise.all(selectedCountries.map(async (country) => {
      try {
        const response = await axios.post(`${API_URL}/api/proxy/scrape-price`, {
          url: resolvedUrl,
          geo: country.name,
          currency: selectedCurrency.code,
          includeMobile,
        }, {
          headers: token ? { Authorization: `Bearer ${token}` } : {},
        });
        onResults(prev => [
          ...prev.filter(r => !(r.slotId === slot.id && r.country.code === country.code)),
          { slotId: slot.id, url: resolvedUrl, country, loading: false, error: null, data: response.data },
        ]);
      } catch (err: unknown) {
        if (axios.isAxiosError(err) && err.response?.status === 429 && err.response.data?.limitReached) {
          const { plan, limit } = err.response.data;
          // Replace all loading results for this slot with a single upgrade card
          onResults(prev => [
            ...prev.filter(r => r.slotId !== slot.id),
            { slotId: slot.id, url: resolvedUrl, country, loading: false, error: null, data: null, limitReached: { plan, limit } },
          ]);
          return;
        }
        const message = err instanceof Error ? err.message : 'Search failed';
        onResults(prev => [
          ...prev.filter(r => !(r.slotId === slot.id && r.country.code === country.code)),
          { slotId: slot.id, url: resolvedUrl, country, loading: false, error: message, data: null },
        ]);
      }
    }));
  }

  return (
    <section id="search-section" className="relative z-10 pt-0">
      <div className={`max-w-6xl mx-auto px-4 sm:px-6 ${compact ? 'pt-6 pb-24' : 'py-16'}`}>
        {/* Options bar */}
        <div className="bg-brand-yellow rounded-t-xl px-4 py-2 flex items-center gap-2 shadow-lg">
          <span className="text-sm font-semibold text-gray-800">{t('optionsLabel')}</span>
        </div>

        <div className="border border-brand-yellow rounded-b-xl p-4 bg-white" ref={countryPickerRef}>
          <div className="flex flex-wrap items-center gap-3">
            {/* Country picker trigger — only in manual mode */}
            {manualMode && (
              <button
                onClick={() => { setShowCountryPicker(!showCountryPicker); setShowCurrencyPicker(false); setCountrySearch(''); }}
                className="flex items-center gap-1.5 border border-gray-300 rounded-md px-3 py-1.5 text-sm hover:border-gray-400 transition-colors bg-white shrink-0"
              >
                {selectedCountries.map(c => (
                  <span key={c.code} title={c.name} className="whitespace-nowrap">{c.flag} {c.code}</span>
                ))}
                <svg className="w-3 h-3 text-gray-400 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                </svg>
              </button>
            )}

            {/* Currency selector */}
            <div className="relative" ref={currencyRef}>
              <button
                onClick={() => { setShowCurrencyPicker(!showCurrencyPicker); setShowCountryPicker(false); }}
                className="flex items-center gap-1.5 border border-gray-300 rounded-md px-3 py-1.5 text-sm hover:border-gray-400 transition-colors bg-white"
              >
                <span className="font-medium">{selectedCurrency.symbol}</span>
                <span>{selectedCurrency.code}</span>
                <svg className="w-3 h-3 text-gray-400 ml-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                </svg>
              </button>
              {showCurrencyPicker && (
                <div className="absolute top-full left-0 mt-1 bg-white border border-gray-200 rounded-xl shadow-lg z-50 w-48 max-h-52 overflow-y-auto">
                  {CURRENCIES.map(c => (
                    <button
                      key={c.code}
                      onClick={() => { setSelectedCurrency(c); setShowCurrencyPicker(false); }}
                      className={`w-full flex items-center gap-2 px-3 py-2 text-sm hover:bg-purple-50 transition-colors text-left ${selectedCurrency.code === c.code ? 'bg-purple-50 font-medium text-brand-purple' : 'text-gray-700'}`}
                    >
                      <span className="w-8 text-right font-mono">{c.symbol}</span>
                      <span>{c.code}</span>
                      <span className="text-gray-400 text-xs truncate">{c.name}</span>
                    </button>
                  ))}
                </div>
              )}
            </div>

            {/* Mobile checkbox */}
            <label className="flex items-center gap-2 cursor-pointer select-none text-sm text-gray-700">
              <input
                type="checkbox"
                checked={includeMobile}
                onChange={e => setIncludeMobile(e.target.checked)}
                className="w-4 h-4 accent-brand-purple rounded"
              />
              {t('mobileLabel')}
            </label>

            {/* Manual search toggle */}
            <label className="flex items-center gap-2 cursor-pointer select-none text-sm text-gray-700">
              <button
                onClick={() => { setManualMode(m => !m); setShowCountryPicker(false); }}
                className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${manualMode ? 'bg-gray-800' : 'bg-gray-300'}`}
                aria-pressed={manualMode}
                aria-label="Toggle manual search"
              >
                <span className={`inline-block h-3.5 w-3.5 rounded-full bg-white shadow transition-transform ${manualMode ? 'translate-x-4' : 'translate-x-1'}`} />
              </button>
              {t('manualLabel')}
            </label>

            {/* Add slot button */}
            <button
              onClick={addSlot}
              disabled={slots.length >= 6}
              className="flex items-center gap-1 text-sm text-brand-purple border border-brand-purple rounded-md px-3 py-1.5 hover:bg-purple-50 transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
            >
              {t('addSlot')}
            </button>
          </div>

          {/* Country picker panel */}
          {showCountryPicker && (
            <div className="mt-3 border border-gray-200 rounded-xl bg-white shadow-lg overflow-hidden">
              <div className="p-3 border-b border-gray-100 bg-gray-50">
                <div className="flex items-center gap-2">
                  <input
                    type="text"
                    value={countrySearch}
                    onChange={e => setCountrySearch(e.target.value)}
                    placeholder={tc('searchCountries')}
                    className="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm bg-white focus:ring-2 focus:ring-brand-purple/30 focus:border-brand-purple outline-none"
                    autoFocus
                  />
                  <button
                    onClick={() => { setShowCountryPicker(false); setCountrySearch(''); }}
                    className="shrink-0 text-sm font-medium text-white bg-brand-purple hover:bg-purple-700 px-3 py-2 rounded-lg transition-colors"
                  >
                    {tc('done')}
                  </button>
                </div>
                <p className="text-[11px] text-gray-400 mt-1.5">
                  {maxCountries > 1
                    ? t('countryPickerMulti', { max: maxCountries, count: selectedCountries.length })
                    : isAuthenticated
                    ? t('countryPickerUpgradePaid')
                    : t('countryPickerUpgradeGuest')}
                </p>
              </div>
              <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-1 p-2 max-h-64 overflow-y-auto">
                {filteredCountries.map(country => {
                  const isSelected = selectedCountries.some(c => c.code === country.code);
                  const isDisabled = maxCountries > 1 && !isSelected && selectedCountries.length >= maxCountries;
                  return (
                    <button
                      key={country.code}
                      onClick={() => toggleCountry(country)}
                      disabled={isDisabled}
                      className={`flex items-center gap-1.5 px-2 py-1.5 rounded-lg text-sm text-left transition-colors ${
                        isSelected
                          ? 'bg-purple-50 border border-brand-purple/30 font-medium text-brand-purple'
                          : 'border border-transparent hover:bg-gray-50 text-gray-700'
                      } ${isDisabled ? 'opacity-30 cursor-not-allowed' : ''}`}
                    >
                      <span>{country.flag}</span>
                      <span className="truncate">{country.name}</span>
                    </button>
                  );
                })}
              </div>
            </div>
          )}
          </div>

        {/* URL slots */}
        <div className="mt-4 flex flex-col gap-3">
          {slots.map(slot => (
            <div key={slot.id} className="flex flex-col gap-2 min-[380px]:flex-row">
              <div className="flex gap-2 min-[380px]:flex-1">
                <input
                  type="url"
                  value={slot.url}
                  onChange={e => updateUrl(slot.id, e.target.value)}
                  onKeyDown={e => { if (e.key === 'Enter') searchSlot(slot); }}
                  placeholder={isAuthenticated ? t('urlPlaceholderAuth') : t('urlPlaceholderGuest')}
                  className="flex-1 border border-gray-300 rounded-lg px-4 py-2.5 text-sm outline-none focus:border-brand-purple focus:ring-1 focus:ring-brand-purple transition"
                />
                {slots.length > 1 && (
                  <button
                    onClick={() => removeSlot(slot.id)}
                    className="text-gray-400 hover:text-gray-600 px-2 text-lg shrink-0"
                    title="Remove"
                  >
                    ×
                  </button>
                )}
              </div>
              <button
                onClick={() => searchSlot(slot)}
                disabled={!slot.url.trim()}
                className="w-full bg-brand-purple hover:bg-purple-700 text-white text-sm font-medium px-5 py-2.5 rounded-lg transition-colors disabled:opacity-40 disabled:cursor-not-allowed min-[380px]:w-auto"
              >
                {t('searchButton')}
              </button>
            </div>
          ))}
        </div>

        {/* Search hint — shown in compact mode or when unauthenticated, hidden once a URL is entered */}
        {(compact || !isAuthenticated) && slots.every(s => !s.url.trim()) && (
          <div className="mt-3 flex items-start gap-2.5 px-3 py-2.5 rounded-lg bg-white/80">
            <div className="mt-0.5 shrink-0 w-5 h-5 rounded-full bg-brand-purple/10 flex items-center justify-center">
              <svg className="w-3 h-3 text-brand-purple" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M5 10l7-7m0 0l7 7m-7-7v18" />
              </svg>
            </div>
            <p className="text-sm text-gray-400 leading-snug">
              {t('hintPreamble')}{' '}
              {t.rich('hintBody', {
                booking: () => <span className="text-gray-500 font-medium">Booking.com</span>,
                airbnb: () => <span className="text-gray-500 font-medium">Airbnb</span>,
                expedia: () => <span className="text-gray-500 font-medium">Expedia</span>,
                otherLink: () => (
                  <button
                    onClick={() => setShowPlatformsModal(true)}
                    className="text-gray-500 font-medium underline underline-offset-2 hover:text-brand-purple transition-colors"
                  >
                    {t('hintOtherLink')}
                  </button>
                ),
              })}
            </p>
          </div>
        )}
      </div>

      {/* Supported platforms lightbox */}
      {showPlatformsModal && (
        <div
          className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm"
          onClick={() => setShowPlatformsModal(false)}
        >
          <div
            className="bg-white rounded-2xl shadow-2xl w-full max-w-2xl max-h-[80vh] flex flex-col"
            onClick={e => e.stopPropagation()}
          >
            {/* Header */}
            <div className="flex items-center justify-between px-4 py-3 border-b border-gray-100 shrink-0 sm:px-6 sm:py-4">
              <div>
                <h2 className="text-base font-bold text-gray-900">{t('supportedPlatformsTitle')}</h2>
                <p className="text-xs text-gray-400 mt-0.5">{t('supportedPlatformsSubtitle')}</p>
              </div>
              <button
                onClick={() => setShowPlatformsModal(false)}
                className="p-1.5 rounded-lg text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors"
                aria-label="Close"
              >
                <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
                </svg>
              </button>
            </div>

            {/* Grid */}
            <div className="overflow-y-auto p-3 sm:p-6">
              <div className="grid grid-cols-3 gap-3 sm:grid-cols-4 sm:gap-5">
                {SUPPORTED_SERVICES.map(service => (
                  <div key={service.name} className="flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-gray-50 transition-colors">
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img
                      src={service.logo}
                      alt={service.name}
                      className="h-8 w-auto object-contain"
                    />
                    <span className="text-xs text-gray-500 text-center leading-tight">{service.name}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}
