/**
 * useLocalWeather Hook
 * Fetches detailed weather data from Open-Meteo API (free, no API key)
 * 
 * Always fetches in metric (Celsius, km/h, mm) and converts client-side.
 * This prevents rounding drift when toggling F↔C (the old approach refetched
 * the API in the new unit, Math.round'd, then back-converted in the header,
 * causing ±1° drift each toggle).
 */
import { useState, useEffect } from 'react';

// Weather code to description and icon mapping
const WEATHER_CODES = {
  0: { desc: 'Clear sky', icon: '☀️' },
  1: { desc: 'Mainly clear', icon: '🌤️' },
  2: { desc: 'Partly cloudy', icon: '⛅' },
  3: { desc: 'Overcast', icon: '☁️' },
  45: { desc: 'Fog', icon: '🌫️' },
  48: { desc: 'Depositing rime fog', icon: '🌫️' },
  51: { desc: 'Light drizzle', icon: '🌧️' },
  53: { desc: 'Moderate drizzle', icon: '🌧️' },
  55: { desc: 'Dense drizzle', icon: '🌧️' },
  56: { desc: 'Light freezing drizzle', icon: '🌧️' },
  57: { desc: 'Dense freezing drizzle', icon: '🌧️' },
  61: { desc: 'Slight rain', icon: '🌧️' },
  63: { desc: 'Moderate rain', icon: '🌧️' },
  65: { desc: 'Heavy rain', icon: '🌧️' },
  66: { desc: 'Light freezing rain', icon: '🌧️' },
  67: { desc: 'Heavy freezing rain', icon: '🌧️' },
  71: { desc: 'Slight snow', icon: '🌨️' },
  73: { desc: 'Moderate snow', icon: '🌨️' },
  75: { desc: 'Heavy snow', icon: '❄️' },
  77: { desc: 'Snow grains', icon: '🌨️' },
  80: { desc: 'Slight rain showers', icon: '🌦️' },
  81: { desc: 'Moderate rain showers', icon: '🌦️' },
  82: { desc: 'Violent rain showers', icon: '⛈️' },
  85: { desc: 'Slight snow showers', icon: '🌨️' },
  86: { desc: 'Heavy snow showers', icon: '❄️' },
  95: { desc: 'Thunderstorm', icon: '⛈️' },
  96: { desc: 'Thunderstorm w/ slight hail', icon: '⛈️' },
  99: { desc: 'Thunderstorm w/ heavy hail', icon: '⛈️' }
};

// Wind direction from degrees
function windDirection(deg) {
  if (deg == null) return '';
  const dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
  return dirs[Math.round(deg / 22.5) % 16];
}

// Conversion helpers — always from Celsius/metric base
const cToF = (c) => c * 9 / 5 + 32;
const kmhToMph = (k) => k * 0.621371;
const mmToInch = (mm) => mm * 0.0393701;
const kmToMi = (km) => km * 0.621371;

export const useLocalWeather = (location, tempUnit = 'F') => {
  const [rawData, setRawData] = useState(null);
  const [loading, setLoading] = useState(true);

  // Fetch always in metric — only depends on location, NOT tempUnit
  useEffect(() => {
    if (!location?.lat || !location?.lon) return;

    const fetchWeather = async () => {
      try {
        const params = [
          `latitude=${location.lat}`,
          `longitude=${location.lon}`,
          'current=temperature_2m,relative_humidity_2m,apparent_temperature,weather_code,cloud_cover,pressure_msl,wind_speed_10m,wind_direction_10m,wind_gusts_10m,precipitation,uv_index,visibility,dew_point_2m,is_day',
          'daily=temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,weather_code,sunrise,sunset,uv_index_max,wind_speed_10m_max',
          'hourly=temperature_2m,precipitation_probability,weather_code',
          'temperature_unit=celsius',
          'wind_speed_unit=kmh',
          'precipitation_unit=mm',
          'timezone=auto',
          'forecast_days=3',
          'forecast_hours=24',
        ].join('&');
        
        const url = `https://api.open-meteo.com/v1/forecast?${params}`;
        const response = await fetch(url);
        if (!response.ok) throw new Error(`HTTP ${response.status}`);
        const result = await response.json();
        
        // Store raw metric values — conversion happens at read time
        setRawData(result);
      } catch (err) {
        console.error('Weather error:', err);
      } finally {
        setLoading(false);
      }
    };

    fetchWeather();
    const interval = setInterval(fetchWeather, 15 * 60 * 1000); // 15 minutes
    return () => clearInterval(interval);
  }, [location?.lat, location?.lon]); // Note: no tempUnit dependency

  // Convert raw API data to display data based on current tempUnit
  // This runs on every render where tempUnit changes — instant, no API call
  const data = (() => {
    if (!rawData) return null;

    const isMetric = tempUnit === 'C';
    const current = rawData.current || {};
    const daily = rawData.daily || {};
    const hourly = rawData.hourly || {};
    const code = current.weather_code;
    const weather = WEATHER_CODES[code] || { desc: 'Unknown', icon: '🌡️' };

    // Temperature conversion (raw is always Celsius)
    const convTemp = (c) => c == null ? null : Math.round(isMetric ? c : cToF(c));
    // Wind conversion (raw is always km/h)
    const convWind = (k) => k == null ? null : Math.round(isMetric ? k : kmhToMph(k));

    // Build hourly forecast (next 24h in 3h intervals)
    const hourlyForecast = [];
    if (hourly.time && hourly.temperature_2m) {
      for (let i = 0; i < Math.min(24, hourly.time.length); i += 3) {
        const hCode = hourly.weather_code?.[i];
        const hWeather = WEATHER_CODES[hCode] || { desc: '', icon: '🌡️' };
        hourlyForecast.push({
          time: new Date(hourly.time[i]).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false }),
          temp: convTemp(hourly.temperature_2m[i]),
          precipProb: hourly.precipitation_probability?.[i] || 0,
          icon: hWeather.icon,
        });
      }
    }
    
    // Build daily forecast
    const dailyForecast = [];
    if (daily.time) {
      for (let i = 0; i < Math.min(3, daily.time.length); i++) {
        const dCode = daily.weather_code?.[i];
        const dWeather = WEATHER_CODES[dCode] || { desc: '', icon: '🌡️' };
        dailyForecast.push({
          date: new Date(daily.time[i] + 'T12:00:00').toLocaleDateString([], { weekday: 'short' }),
          high: convTemp(daily.temperature_2m_max?.[i]),
          low: convTemp(daily.temperature_2m_min?.[i]),
          precipProb: daily.precipitation_probability_max?.[i] || 0,
          precipSum: isMetric 
            ? (daily.precipitation_sum?.[i] || 0)
            : parseFloat(mmToInch(daily.precipitation_sum?.[i] || 0).toFixed(2)),
          icon: dWeather.icon,
          desc: dWeather.desc,
          windMax: convWind(daily.wind_speed_10m_max?.[i]),
          uvMax: daily.uv_index_max?.[i] || 0,
        });
      }
    }

    // Raw Celsius values for Header's dual F/C display
    const rawTempC = current.temperature_2m || 0;

    return {
      // Current conditions (converted to user's preferred unit)
      temp: convTemp(current.temperature_2m),
      feelsLike: convTemp(current.apparent_temperature),
      description: weather.desc,
      icon: weather.icon,
      humidity: Math.round(current.relative_humidity_2m || 0),
      dewPoint: convTemp(current.dew_point_2m),
      pressure: current.pressure_msl ? current.pressure_msl.toFixed(1) : null,
      cloudCover: current.cloud_cover || 0,
      windSpeed: convWind(current.wind_speed_10m),
      windDir: windDirection(current.wind_direction_10m),
      windDirDeg: current.wind_direction_10m || 0,
      windGusts: convWind(current.wind_gusts_10m),
      precipitation: isMetric 
        ? (current.precipitation || 0) 
        : parseFloat(mmToInch(current.precipitation || 0).toFixed(2)),
      uvIndex: current.uv_index || 0,
      visibility: current.visibility 
        ? isMetric 
          ? (current.visibility / 1000).toFixed(1)  // meters to km
          : kmToMi(current.visibility / 1000).toFixed(1) // meters to km to miles
        : null,
      isDay: current.is_day === 1,
      weatherCode: code,
      // Today's highs/lows
      todayHigh: convTemp(daily.temperature_2m_max?.[0]),
      todayLow: convTemp(daily.temperature_2m_min?.[0]),
      // Forecasts
      hourly: hourlyForecast,
      daily: dailyForecast,
      // Timezone
      timezone: rawData.timezone || '',
      // Units (for display labels)
      tempUnit: isMetric ? 'C' : 'F',
      windUnit: isMetric ? 'km/h' : 'mph',
      visUnit: isMetric ? 'km' : 'mi',
      // Raw Celsius for Header's dual display (avoids double-rounding)
      rawTempC,
      rawFeelsLikeC: current.apparent_temperature || 0,
    };
  })();

  return { data, loading };
};

export default useLocalWeather;
