import { Wind } from 'lucide-react';
import { useEffect, useState } from 'react';
import { fetchContextWithGeolocation } from '@/lib/geoDevice';

const WeatherWidget = () => {
  const [data, setData] = useState({
    temperature: 0,
    condition: '',
    location: '',
    humidity: 0,
    windSpeed: 0,
    icon: '',
    temperatureUnit: 'C',
    windSpeedUnit: 'm/s',
  });

  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);

  const fetchWeather = async (
    lat: number,
    lng: number,
    city: string,
  ) => {
    const res = await fetch('/api/weather', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        lat,
        lng,
        city: city || undefined,
        measureUnit: localStorage.getItem('measureUnit') ?? 'Metric',
      }),
    });

    const weatherData = await res.json();

    if (res.status !== 200) {
      throw new Error(weatherData.message ?? 'Weather fetch failed');
    }

    setData({
      temperature: weatherData.temperature,
      condition: weatherData.condition,
      location: weatherData.city ?? city ?? 'Unknown',
      humidity: weatherData.humidity,
      windSpeed: weatherData.windSpeed,
      icon: weatherData.icon,
      temperatureUnit: weatherData.temperatureUnit,
      windSpeedUnit: weatherData.windSpeedUnit,
    });
  };

  const updateWeather = async () => {
    setError(false);
    setLoading(true);

    try {
      let context: Awaited<ReturnType<typeof fetchContextWithGeolocation>> | null =
        null;
      try {
        context = await fetchContextWithGeolocation();
      } catch {
        // geo-device не запущен (503) — пропускаем
      }

      if (context?.geo?.latitude != null && context.geo.longitude != null) {
        const city =
          context.geo.city ||
          (await reverseGeocode(context.geo.latitude, context.geo.longitude));
        await fetchWeather(
          context.geo.latitude,
          context.geo.longitude,
          city,
        );
      } else {
        await tryIpFallback();
      }
    } catch {
      await tryIpFallback();
    } finally {
      setLoading(false);
    }
  };

  const reverseGeocode = async (
    lat: number,
    lng: number,
  ): Promise<string> => {
    try {
      const res = await fetch(
        `https://api-bdc.io/data/reverse-geocode-client?latitude=${lat}&longitude=${lng}&localityLanguage=en`,
      );
      const d = await res.json();
      return d?.locality ?? '';
    } catch {
      return '';
    }
  };

  const tryIpFallback = async () => {
    const providers: Array<{
      url: string;
      getCoords: (d: Record<string, unknown>) => { lat: number; lng: number; city: string } | null;
    }> = [
      {
        url: 'https://get.geojs.io/v1/ip/geo.json',
        getCoords: (d) => {
          const lat = Number(d.latitude);
          const lng = Number(d.longitude);
          if (Number.isFinite(lat) && Number.isFinite(lng)) {
            return {
              lat,
              lng,
              city: String(d.city ?? d.region ?? '').trim() || 'Unknown',
            };
          }
          return null;
        },
      },
      {
        url: 'https://ipwhois.app/json/',
        getCoords: (d) => {
          const lat = Number(d.latitude);
          const lng = Number(d.longitude);
          if (Number.isFinite(lat) && Number.isFinite(lng)) {
            return {
              lat,
              lng,
              city: String(d.city ?? '').trim() || 'Unknown',
            };
          }
          return null;
        },
      },
    ];

    for (const p of providers) {
      try {
        const res = await fetch(p.url);
        const d = (await res.json()) as Record<string, unknown>;
        const coords = p.getCoords(d);
        if (coords) {
          await fetchWeather(coords.lat, coords.lng, coords.city || 'Unknown');
          return;
        }
      } catch {
        // следующий провайдер
      }
    }
    setError(true);
  };

  useEffect(() => {
    updateWeather();
    const intervalId = setInterval(updateWeather, 30 * 60 * 1000);
    return () => clearInterval(intervalId);
  }, []);

  return (
    <div className="bg-light-secondary dark:bg-dark-secondary rounded-2xl border border-light-200 dark:border-dark-200 shadow-sm shadow-light-200/10 dark:shadow-black/25 flex flex-row items-center w-full h-24 min-h-[96px] max-h-[96px] px-3 py-2 gap-3">
      {error ? (
        <div className="flex items-center justify-center w-full h-full text-xs text-black/50 dark:text-white/50">
          Weather unavailable
        </div>
      ) : loading ? (
        <>
          <div className="flex flex-col items-center justify-center w-16 min-w-16 max-w-16 h-full animate-pulse">
            <div className="h-10 w-10 rounded-full bg-light-200 dark:bg-dark-200 mb-2" />
            <div className="h-4 w-10 rounded bg-light-200 dark:bg-dark-200" />
          </div>
          <div className="flex flex-col justify-between flex-1 h-full py-1 animate-pulse">
            <div className="flex flex-row items-center justify-between">
              <div className="h-3 w-20 rounded bg-light-200 dark:bg-dark-200" />
              <div className="h-3 w-12 rounded bg-light-200 dark:bg-dark-200" />
            </div>
            <div className="h-3 w-16 rounded bg-light-200 dark:bg-dark-200 mt-1" />
            <div className="flex flex-row justify-between w-full mt-auto pt-1 border-t border-light-200 dark:border-dark-200">
              <div className="h-3 w-16 rounded bg-light-200 dark:bg-dark-200" />
              <div className="h-3 w-8 rounded bg-light-200 dark:bg-dark-200" />
            </div>
          </div>
        </>
      ) : (
        <>
          <div className="flex flex-col items-center justify-center w-16 min-w-16 max-w-16 h-full">
            <img
              src={`/weather-ico/${data.icon}.svg`}
              alt={data.condition}
              className="h-10 w-auto"
            />
            <span className="text-base font-semibold text-black dark:text-white">
              {data.temperature}°{data.temperatureUnit}
            </span>
          </div>
          <div className="flex flex-col justify-between flex-1 h-full py-2">
            <div className="flex flex-row items-center justify-between">
              <span className="text-sm font-semibold text-black dark:text-white">
                {data.location}
              </span>
              <span className="flex items-center text-xs text-black/60 dark:text-white/60 font-medium">
                <Wind className="w-3 h-3 mr-1" />
                {data.windSpeed} {data.windSpeedUnit}
              </span>
            </div>
            <span className="text-xs text-black/50 dark:text-white/50 italic">
              {data.condition}
            </span>
            <div className="flex flex-row justify-between w-full mt-auto pt-2 border-t border-light-200/50 dark:border-dark-200/50 text-xs text-black/50 dark:text-white/50 font-medium">
              <span>Humidity {data.humidity}%</span>
              <span className="font-semibold text-black/70 dark:text-white/70">
                Now
              </span>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

export default WeatherWidget;
