import { useMemo, useState, useCallback } from 'react'
import Highcharts from 'highcharts'
import { HighchartsReact } from 'highcharts-react-official'
import { format } from 'date-fns'
import { de } from 'date-fns/locale'
import './WeatherDashboard.css'
// Build-Informationen (werden beim Build eingef\u00fcgt)
const buildDate = __BUILD_DATE__
const version = __VERSION__
// Deutsche Lokalisierung für Highcharts
Highcharts.setOptions({
  lang: {
    months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
    shortMonths: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
    weekdays: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
    resetZoom: 'Zoom zurücksetzen'
  },
  time: {
    useUTC: false
  }
})

const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '24h', onTimeRangeChange, showTable = false, onToggleTable }) => {
  // State für Anleitung
  const [showAnleitung, setShowAnleitung] = useState(false)

  // Schwellwert für Datenlücken (abhängig vom Zeitraum)
  const gapThresholdMs = useMemo(() => {
    if (timeRange === '24h') return 2 * 60 * 60 * 1000        // 2 Stunden
    return 1.5 * 24 * 3600 * 1000                             // 1,5 Tage
  }, [timeRange])

  // Fügt null-Einträge in Lücken ein, damit Highcharts die Linie unterbricht
  const withGaps = useCallback((pairs) => {
    const result = []
    for (let i = 0; i < pairs.length; i++) {
      result.push(pairs[i])
      if (i < pairs.length - 1 && pairs[i + 1][0] - pairs[i][0] > gapThresholdMs) {
        result.push([(pairs[i][0] + pairs[i + 1][0]) / 2, null])
      }
    }
    return result
  }, [gapThresholdMs])

  // State für benutzerdefinierten Zeitbereich
  const [showCustomRangeModal, setShowCustomRangeModal] = useState(false)
  const [customStartDate, setCustomStartDate] = useState('')
  const [customEndDate, setCustomEndDate] = useState('')
  const [customError, setCustomError] = useState('')
  
  // Handler für benutzerdefinierten Zeitbereich
  const handleOpenCustomRange = () => {
    // Versuche gespeicherten Zeitbereich zu laden
    try {
      const savedRange = localStorage.getItem('customTimeRange')
      if (savedRange) {
        const { start, end } = JSON.parse(savedRange)
        setCustomStartDate(start.split('T')[0])
        setCustomEndDate(end.split('T')[0])
      } else {
        // Setze Standardwerte (letzte 7 Tage)
        const end = new Date()
        const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000)
        
        setCustomStartDate(format(start, 'yyyy-MM-dd'))
        setCustomEndDate(format(end, 'yyyy-MM-dd'))
      }
    } catch (e) {
      // Bei Fehler: Standardwerte verwenden
      const end = new Date()
      const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000)
      
      setCustomStartDate(format(start, 'yyyy-MM-dd'))
      setCustomEndDate(format(end, 'yyyy-MM-dd'))
    }
    
    setCustomError('')
    setShowCustomRangeModal(true)
  }
  
  const handleApplyCustomRange = () => {
    if (!customStartDate || !customEndDate) {
      setCustomError('Bitte Start- und Enddatum auswählen')
      return
    }
    
    const diffDays = Math.floor((new Date(customEndDate) - new Date(customStartDate)) / (1000 * 60 * 60 * 24))
    
    if (diffDays < 0) {
      setCustomError('Enddatum muss nach dem Startdatum liegen')
      return
    }
    
    if (diffDays > 365) {
      setCustomError('Maximaler Zeitraum ist 1 Jahr (365 Tage)')
      return
    }
    
    const startStr = customStartDate + 'T00:00'
    const endStr = customEndDate + 'T23:59'
    
    // Zeitbereich im localStorage speichern
    try {
      localStorage.setItem('customTimeRange', JSON.stringify({
        start: customStartDate,
        end: customEndDate
      }))
    } catch (e) {
      // Fehler beim Speichern ignorieren
      console.warn('Konnte Zeitbereich nicht speichern:', e)
    }
    
    // Anwenden
    onTimeRangeChange('custom', { start: startStr, end: endStr })
    setShowCustomRangeModal(false)
  }
  
  const handleCancelCustomRange = () => {
    setShowCustomRangeModal(false)
    setCustomError('')
  }
  
  // Daten vorbereiten und nach Zeit sortieren (älteste zuerst)
  const sortedData = useMemo(() => {
    return [...data].sort((a, b) => new Date(a.datetime) - new Date(b.datetime))
  }, [data])
  
  // Aktuelle Werte aus separaten currentData (immer 24h)
  const sortedCurrentData = useMemo(() => {
    return [...currentData].sort((a, b) => new Date(a.datetime) - new Date(b.datetime))
  }, [currentData])
  
  // Zeitraum-Label
  const timeRangeLabel = useMemo(() => {
    if (typeof timeRange === 'object' && timeRange.type === 'custom') {
      const start = new Date(timeRange.start)
      const end = new Date(timeRange.end)
      return `${format(start, 'dd.MM.yyyy HH:mm', { locale: de })} - ${format(end, 'dd.MM.yyyy HH:mm', { locale: de })}`
    }
    switch (timeRange) {
      case '24h': return 'Die letzten 24 Stunden'
      case '7d': return 'Die letzten 7 Tage'
      case '30d': return 'Die letzten 30 Tage'
      case '365d': return 'Die letzten 365 Tage'
      default: return 'Die letzten 24 Stunden'
    }
  }, [timeRange])

  // Aggregations-Zusatz für Chart-Titel
  const aggregationSuffix = useMemo(() => {
    // Custom range: basierend auf days
    if (typeof timeRange === 'object' && timeRange.type === 'custom') {
      const days = timeRange.days || 1
      if (days >= 7) {
        return ' (Tagesmittel)'
      } else {
        return ' (Stundenmittel)'
      }
    }
    // Vordefinierte Bereiche
    switch (timeRange) {
      case '7d':
      case '30d':
      case '365d':
        return ' (Tagesmittel)'
      default:
        return ''
    }
  }, [timeRange])

  // Spezieller Suffix für Regen
  const rainSuffix = useMemo(() => {
    if (typeof timeRange === 'object' && timeRange.type === 'custom') {
      return ' (pro Tag)'
    }
    switch (timeRange) {
      case '7d':
      case '30d':
        return ' (pro Tag)'
      case '365d':
        return ' (pro Woche)'
      default:
        return ''
    }
  }, [timeRange])

  // Spezieller Suffix für Temperatur bei 30d/365d
  const temperatureSuffix = useMemo(() => {
    // Custom range: basierend auf days
    if (typeof timeRange === 'object' && timeRange.type === 'custom') {
      const days = timeRange.days || 1
      if (days >= 7) {
        return ' (Tages-Min/Max)'
      }
      return ''
    }
    // Vordefinierte Bereiche
    switch (timeRange) {
      case '7d':
      case '30d':
      case '365d':
        return ' (Tages-Min/Max)'
      default:
        return ''
    }
  }, [timeRange])

  // Spezieller Suffix für Windböen bei 30d/365d
  const windGustSuffix = useMemo(() => {
    // Custom range: basierend auf days
    if (typeof timeRange === 'object' && timeRange.type === 'custom') {
      const days = timeRange.days || 1
      if (days >= 7) {
        return ' (TagesMax)'
      }
      return ''
    }
    // Vordefinierte Bereiche
    switch (timeRange) {
      case '7d':
      case '30d':
      case '365d':
        return ' (TagesMax)'
      default:
        return ''
    }
  }, [timeRange])

  // Hilfsfunktion: Dynamischen Y-Bereich berechnen.
  // minHalfSpan: halbe Mindestspanne (z.B. 5 → Bereich mind. 10 Einheiten)
  const calcYRange = (values, minHalfSpan) => {
    if (values.length === 0) return { yMin: null, yMax: null }
    const min = Math.min(...values)
    const max = Math.max(...values)
    if (max - min < minHalfSpan * 2) {
      const center = (max + min) / 2
      return { yMin: center - minHalfSpan, yMax: center + minHalfSpan }
    }
    return { yMin: min, yMax: max }
  }

  // Hilfsfunktion: BarTrend-Wert (Davis VantagePro) → Pfeil + Label
  // Werte laut Davis Serial Communication Reference Rev 2.6.1:
  // -60 = Falling Rapidly, -20 = Falling Slowly, 0 = Steady,
  //  20 = Rising Slowly,   60 = Rising Rapidly,  80/'P' = kein Trend
  const barTrendArrow = (trend) => {
    switch (trend) {
      case -60: return { arrow: '⬇⬇', label: 'Fällt schnell' }
      case -20: return { arrow: '⬇',  label: 'Fällt langsam' }
      case   0: return { arrow: '→',  label: 'Stabil' }
      case  20: return { arrow: '⬆',  label: 'Steigt langsam' }
      case  60: return { arrow: '⬆⬆', label: 'Steigt schnell' }
      default:  return null
    }
  }

  // Gemeinsame Chart-Optionen (angepasst an Zeitraum)
  const getCommonOptions = () => {
    // Prüfe, ob es ein custom range ist
    const isCustomRange = typeof timeRange === 'object' && timeRange.type === 'custom'
    const customDays = isCustomRange ? (timeRange.days || 1) : 0
    
    // X-Achsen-Konfiguration basierend auf Zeitraum
    let xAxisConfig = {
      type: 'datetime',
      gridLineWidth: 1,
      gridLineColor: 'rgba(0, 0, 0, 0.1)'
    }
    
    // Zeitspanne für X-Achse berechnen (für festen Zeitrahmen)
    const now = new Date().getTime()
    let xAxisMin, xAxisMax
    let tooltipDateFormat = '%d.%m.%Y'
    
    if (isCustomRange) {
      // Custom range Konfiguration - Min/Max aus Daten nehmen
      if (customDays >= 7) {
        xAxisConfig.labels = { format: '{value:%d.%m}', align: 'center' }
        tooltipDateFormat = '%d.%m.%Y'
      } else {
        xAxisConfig.labels = { format: '{value:%d.%m %H:%M}', align: 'center' }
        tooltipDateFormat = '%d.%m.%Y %H:%M'
      }
      // X-Achsen-Bereich aus den tatsächlichen Daten bestimmen
      if (sortedData.length > 0) {
        xAxisMin = new Date(sortedData[0].datetime).getTime()
        xAxisMax = new Date(sortedData[sortedData.length - 1].datetime).getTime()
      } else {
        xAxisMin = null
        xAxisMax = null
      }
    } else {
      // Vordefinierte Bereiche
      const pad = n => String(n).padStart(2, '0')
      const fmtDate = d => `${pad(d.getDate())}.${pad(d.getMonth() + 1)}`
      const fmtTime = d => `${pad(d.getHours())}:${pad(d.getMinutes())}`

      switch (timeRange) {
        case '24h':
          xAxisConfig.tickPositioner = function() {
            const positions = []
            const d = new Date(this.min)
            d.setMinutes(0, 0, 0)
            const h = d.getHours()
            const nextH = Math.ceil(h / 4) * 4
            if (nextH >= 24) { d.setDate(d.getDate() + 1); d.setHours(0, 0, 0, 0) }
            else d.setHours(nextH, 0, 0, 0)
            while (d.getTime() <= this.max) {
              positions.push(d.getTime())
              d.setHours(d.getHours() + 4, 0, 0, 0)
            }
            return positions
          }
          xAxisConfig.labels = {
            rotation: 0, align: 'center', useHTML: true,
            formatter: function() {
              const d = new Date(this.value)
              return d.getHours() === 0 && d.getMinutes() === 0
                ? `<span style="color:#3b82f6;font-weight:bold">${fmtDate(d)}</span>`
                : fmtTime(d)
            }
          }
          xAxisMin = now - 24 * 3600 * 1000
          xAxisMax = now
          tooltipDateFormat = '%d.%m.%Y %H:%M'
          break
        case '7d':
          xAxisConfig.tickPositioner = function() {
            const positions = []
            const d = new Date(this.min)
            d.setHours(0, 0, 0, 0)
            while (d.getTime() <= this.max) {
              positions.push(d.getTime())
              d.setDate(d.getDate() + 1)
            }
            return positions
          }
          xAxisConfig.labels = {
            rotation: 0, align: 'center',
            formatter: function() { return fmtDate(new Date(this.value)) }
          }
          xAxisMin = now - 7 * 24 * 3600 * 1000
          xAxisMax = now
          tooltipDateFormat = '%d.%m.%Y'
          break
        case '30d':
          xAxisConfig.tickPositioner = function() {
            const positions = []
            const d = new Date(this.min)
            d.setHours(0, 0, 0, 0)
            while (d.getTime() <= this.max) {
              positions.push(d.getTime())
              d.setDate(d.getDate() + 5)
            }
            return positions
          }
          xAxisConfig.labels = {
            rotation: 0, align: 'center',
            formatter: function() { return fmtDate(new Date(this.value)) }
          }
          xAxisMin = now - 30 * 24 * 3600 * 1000
          xAxisMax = now
          tooltipDateFormat = '%d.%m.%Y'
          break
        case '365d':
          xAxisConfig.tickPositioner = function() {
            const positions = []
            const d = new Date(this.min)
            d.setDate(1); d.setHours(0, 0, 0, 0)
            while (d.getTime() <= this.max) {
              positions.push(d.getTime())
              d.setMonth(d.getMonth() + 1)
            }
            return positions
          }
          xAxisConfig.labels = {
            rotation: 0, align: 'center',
            formatter: function() { return pad(new Date(this.value).getMonth() + 1) }
          }
          tooltipDateFormat = '%d.%m.%Y'
          if (sortedData.length > 0) {
            xAxisMin = new Date(sortedData[0].datetime).getTime()
            xAxisMax = new Date(sortedData[sortedData.length - 1].datetime).getTime()
          } else {
            xAxisMin = null
            xAxisMax = null
          }
          break
        default:
          xAxisConfig.tickPositioner = function() {
            const positions = []
            const d = new Date(this.min)
            d.setMinutes(0, 0, 0)
            const h = d.getHours()
            const nextH = Math.ceil(h / 4) * 4
            if (nextH >= 24) { d.setDate(d.getDate() + 1); d.setHours(0, 0, 0, 0) }
            else d.setHours(nextH, 0, 0, 0)
            while (d.getTime() <= this.max) {
              positions.push(d.getTime())
              d.setHours(d.getHours() + 4, 0, 0, 0)
            }
            return positions
          }
          xAxisConfig.labels = {
            rotation: 0, align: 'center',
            formatter: function() {
              const d = new Date(this.value)
              return d.getHours() === 0 && d.getMinutes() === 0 ? fmtDate(d) : fmtTime(d)
            }
          }
          xAxisMin = now - 24 * 3600 * 1000
          xAxisMax = now
          tooltipDateFormat = '%d.%m.%Y %H:%M'
      }
    }
    
    // Min/Max für X-Achse setzen
    xAxisConfig.min = xAxisMin
    xAxisConfig.max = xAxisMax
    
    return {
      chart: {
        height: '50%',
        animation: false,
        backgroundColor: 'transparent'
      },
      accessibility: {
        enabled: false
      },
      credits: {
        enabled: false
      },
      title: {
        text: null
      },
      legend: {
        enabled: false
      },
      tooltip: {
        shared: true,
        crosshairs: true,
        xDateFormat: tooltipDateFormat
      },
      plotOptions: {
        series: {
          marker: {
            enabled: false,
            states: {
              hover: {
                enabled: true,
                radius: 5
              }
            }
          }
        }
      },
      xAxis: xAxisConfig,
      yAxis: {
        gridLineColor: 'rgba(0, 0, 0, 0.05)'
      }
    }
  }

  // Temperatur Chart
  const temperatureOptions = useMemo(() => {
    // Prüfe, ob Min/Max-Temperaturen angezeigt werden sollen
    const isCustomRange = typeof timeRange === 'object' && timeRange.type === 'custom'
    const customDays = isCustomRange ? (timeRange.days || 1) : 0
    const showMinMax = (timeRange === '7d' || timeRange === '30d' || timeRange === '365d') || (isCustomRange && customDays >= 7)
    
    // Bei 7d, 30d, 365d und custom >= 7 Tage: Min/Max-Temperaturen anzeigen
    if (showMinMax) {
      const minTemps = sortedData.filter(item => item.min_temperature != null).map(item => item.min_temperature)
      const maxTemps = sortedData.filter(item => item.max_temperature != null).map(item => item.max_temperature)
      
      // Prüfe, ob Daten vorhanden sind
      if (minTemps.length === 0 || maxTemps.length === 0) {
        return {
          ...getCommonOptions(),
          yAxis: {
            ...getCommonOptions().yAxis,
            title: { text: null }
          },
          series: []
        }
      }
      
      let yMin = Math.min(...minTemps)
      let yMax = Math.max(...maxTemps)
      
      // Füge einen kleinen Puffer hinzu (2°C oben/unten), um den Platz optimal zu nutzen
      yMin = Math.floor(yMin - 2)
      yMax = Math.ceil(yMax + 2)

      return {
        ...getCommonOptions(),
        yAxis: {
          title: { text: null },
          gridLineColor: 'rgba(0, 0, 0, 0.05)',
          min: yMin,
          max: yMax,
          startOnTick: false,
          endOnTick: false
        },
        series: [
          {
            name: 'Maximaltemperatur',
            data: withGaps(sortedData.filter(item => item.max_temperature != null).map(item => [new Date(item.datetime).getTime(), item.max_temperature])),
            color: 'rgb(255, 99, 132)',
            type: 'line',
            lineWidth: 2,
            connectNulls: false,
            gapSize: 2 * 24 * 3600 * 1000,
            gapUnit: 'value',
            tooltip: {
              valueDecimals: 1,
              valueSuffix: ' °C'
            }
          },
          {
            name: 'Minimaltemperatur',
            data: withGaps(sortedData.filter(item => item.min_temperature != null).map(item => [new Date(item.datetime).getTime(), item.min_temperature])),
            color: 'rgb(54, 162, 235)',
            type: 'line',
            lineWidth: 2,
            connectNulls: false,
            gapSize: 2 * 24 * 3600 * 1000,
            gapUnit: 'value',
            tooltip: {
              valueDecimals: 1,
              valueSuffix: ' °C'
            }
          }
        ]
      }
    }
    
    // Standard: Temperatur als Flächendiagramm
    const temps = sortedData.filter(item => item.temperature != null).map(item => item.temperature)
    
    if (temps.length === 0) {
      return {
        ...getCommonOptions(),
        yAxis: {
          ...getCommonOptions().yAxis,
          title: { text: null }
        },
        series: []
      }
    }
    
    const { yMin, yMax } = calcYRange(temps, 5)

    return {
      ...getCommonOptions(),
      yAxis: {
        ...getCommonOptions().yAxis,
        title: { text: null },
        min: yMin,
        max: yMax
      },
      series: [{
        name: 'Temperatur',
        data: withGaps(sortedData.filter(item => item.temperature != null).map(item => [new Date(item.datetime).getTime(), item.temperature])),
        color: 'rgb(255, 99, 132)',
        fillColor: {
          linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
          stops: [
            [0, 'rgba(255, 99, 132, 0.3)'],
            [1, 'rgba(255, 99, 132, 0.1)']
          ]
        },
        type: 'areaspline',
        threshold: null,
        connectNulls: false,
        gapSize: 2 * 24 * 3600 * 1000,
        gapUnit: 'value',
        tooltip: {
          valueDecimals: 1,
          valueSuffix: ' °C'
        }
      }]
    }
  }, [sortedData, temperatureSuffix, timeRange, withGaps])

  // Luftfeuchtigkeit Chart
  const humidityOptions = useMemo(() => {
    const humidities = sortedData.filter(item => item.humidity != null).map(item => item.humidity)
    const { yMin, yMax } = calcYRange(humidities, 10)
    return {
    ...getCommonOptions(),
    yAxis: {
      ...getCommonOptions().yAxis,
      title: { text: null },
      min: yMin,
      max: yMax
    },
    series: [{
      name: 'Feuchte',
      data: withGaps(sortedData.filter(item => item.humidity != null).map(item => [new Date(item.datetime).getTime(), item.humidity])),
      color: 'rgb(54, 162, 235)',
      fillColor: {
        linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
        stops: [
          [0, 'rgba(54, 162, 235, 0.3)'],
          [1, 'rgba(54, 162, 235, 0.1)']
        ]
      },
      type: 'area',
      connectNulls: false,
      gapSize: 2 * 24 * 3600 * 1000,
      gapUnit: 'value',
      tooltip: {
        valueDecimals: 0,
        valueSuffix: ' %'
      }
    }]
  }
  }, [sortedData, timeRange, withGaps])

  // Luftdruck Chart
  const pressureOptions = useMemo(() => {
    const pressures = sortedData.filter(item => item.pressure != null).map(item => item.pressure)
    
    if (pressures.length === 0) {
      return {
        ...getCommonOptions(),
        yAxis: {
          ...getCommonOptions().yAxis,
          title: { text: null }
        },
        series: []
      }
    }
    
    const { yMin, yMax } = calcYRange(pressures, 20)

    return {
      ...getCommonOptions(),
      yAxis: {
        ...getCommonOptions().yAxis,
        title: { text: null },
        min: yMin,
        max: yMax
      },
      series: [{
        name: 'Luftdruck',
        data: withGaps(sortedData.filter(item => item.pressure != null).map(item => [new Date(item.datetime).getTime(), item.pressure])),
        color: 'rgb(75, 192, 192)',
        fillColor: {
          linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
          stops: [
            [0, 'rgba(75, 192, 192, 0.3)'],
            [1, 'rgba(75, 192, 192, 0.1)']
          ]
        },
        type: 'area',
        connectNulls: false,
        gapSize: 2 * 24 * 3600 * 1000,
        gapUnit: 'value',
        tooltip: {
          valueDecimals: 0,
          valueSuffix: ' hPa'
        }
      }]
    }
  }, [sortedData, timeRange, withGaps])

  // Regen Chart (angepasst an Zeitraum)
  const rainOptions = useMemo(() => {
    let series = []
    let yAxisTitle = 'Regen (mm) / Rate (mm/h)'
    
    if (timeRange === '24h') {
      // 24h: Area Chart mit Regen und Regenrate
      yAxisTitle = 'Regen (mm) / Rate (mm/h)'
      series = [{
        name: 'Regen',
        data: sortedData.filter(item => item.rain != null).map(item => [new Date(item.datetime).getTime(), item.rain]),
        color: 'rgb(54, 162, 235)',
        fillColor: 'rgba(54, 162, 235, 0.3)',
        type: 'area',
        tooltip: {
          valueDecimals: 1,
          valueSuffix: ' mm'
        }
      }, {
        name: 'Regenrate',
        data: sortedData.filter(item => item.rain_rate != null).map(item => [new Date(item.datetime).getTime(), item.rain_rate]),
        color: 'rgb(59, 130, 246)',
        dashStyle: 'Dash',
        type: 'line',
        tooltip: {
          valueSuffix: ' mm/h'
        }
      }]
    } else if (timeRange === '7d' || timeRange === '30d') {
      // 7d/30d: Balkendiagramm mit täglichen Summen
      yAxisTitle = 'Regen (mm pro Tag)'
      series = [{
        name: 'Regen',
        data: rainData.filter(item => item.total_rain != null && item.total_rain > 0).map(item => [new Date(item.date).getTime(), item.total_rain]),
        color: 'rgb(54, 162, 235)',
        type: 'column',
        tooltip: {
          valueDecimals: 1,
          valueSuffix: ' mm'
        }
      }]
    } else if (timeRange === '365d') {
      // 365d: Balkendiagramm mit wöchentlichen Summen
      yAxisTitle = 'Regen (mm pro Woche)'
      series = [{
        name: 'Regen',
        data: rainData.filter(item => item.total_rain != null && item.total_rain > 0).map(item => [new Date(item.week_start).getTime(), item.total_rain]),
        color: 'rgb(54, 162, 235)',
        type: 'column',
        tooltip: {
          valueDecimals: 1,
          valueSuffix: ' mm'
        }
      }]
    } else if (typeof timeRange === 'object' && timeRange.type === 'custom') {
      // Custom range: tägliche Summen — bei kurzen Ranges (<7d) aus rainData (extra Fetch),
      // bei langen Ranges aus sortedData (daily-aggregated-range enthält total_rain)
      yAxisTitle = 'Regen (mm pro Tag)'
      const rainSource = rainData.length > 0 ? rainData : sortedData
      series = [{
        name: 'Regen',
        data: rainSource
          .filter(item => item.total_rain != null && item.total_rain > 0)
          .map(item => [new Date(item.datetime).getTime(), item.total_rain]),
        color: 'rgb(54, 162, 235)',
        type: 'column',
        tooltip: {
          valueDecimals: 1,
          valueSuffix: ' mm'
        }
      }]
    }
    
    return {
      ...getCommonOptions(),
      legend: {
        enabled: series.length > 1,
        align: 'right',
        verticalAlign: 'top',
        floating: true,
        itemStyle: { fontSize: '11px', fontWeight: 'normal' }
      },
      yAxis: {
        ...getCommonOptions().yAxis,
        title: { text: null }
      },
      series
    }
  }, [sortedData, rainData, timeRange, withGaps])

  // Windgeschwindigkeit Chart
  const windSpeedOptions = useMemo(() => {
    // Prüfe, ob Böen angezeigt werden sollen (nicht bei 365d oder custom >= 365 Tage)
    const isCustomRange = typeof timeRange === 'object' && timeRange.type === 'custom'
    const customDays = isCustomRange ? (timeRange.days || 1) : 0
    const hideGusts = (timeRange === '365d') || (isCustomRange && customDays >= 365)
    const windSpeedSeries = {
      name: 'Windgeschwindigkeit',
      data: withGaps(sortedData
        .filter(item => item.wind_speed != null)
        .map(item => [new Date(item.datetime).getTime(), item.wind_speed])),
      color: 'rgb(153, 102, 255)',
      fillColor: 'rgba(153, 102, 255, 0.1)',
      type: 'area',
      connectNulls: false,
      gapSize: 2 * 24 * 3600 * 1000,
      gapUnit: 'value',
      tooltip: {
        valueDecimals: 1,
        valueSuffix: ' km/h'
      }
    }

    const gustSeries = {
          name: 'Böe' + windGustSuffix,
          data: withGaps(sortedData
            .filter(item => item.wind_gust != null)
            .map(item => [new Date(item.datetime).getTime(), item.wind_gust])),
          color: 'rgba(255, 160, 80, 0.6)',
          fillColor: 'rgba(255, 160, 80, 0.08)',
          type: 'area',
          lineWidth: 1.5,
          connectNulls: false,
          gapSize: 2 * 24 * 3600 * 1000,
          gapUnit: 'value',
          tooltip: {
            valueDecimals: 1,
            valueSuffix: ' km/h'
          }
        }
    const series = hideGusts
      ? [windSpeedSeries]
      : [gustSeries, windSpeedSeries]
    return {
      ...getCommonOptions(),
      legend: {
        enabled: true,
        align: 'right',
        verticalAlign: 'top',
        floating: true,
        itemStyle: { fontSize: '11px', fontWeight: 'normal' }
      },
      plotOptions: {
        series: {
          marker: {
            enabled: false
          },
          lineWidth: 2
        },
        line: {
          step: 'left' // Keine Glättung
        }
      },
      yAxis: {
        ...getCommonOptions().yAxis,
        title: { text: null },
        min: 0
      },
      series
    }
  }, [sortedData, timeRange, windGustSuffix, withGaps])

  // Windrichtung Chart
  const windDirOptions = useMemo(() => ({
    ...getCommonOptions(),
    tooltip: {
      formatter: function() {
        const dateFormat = timeRange === '24h' ? '%d.%m.%Y %H:%M' : '%d.%m.%Y'
        const dateStr = Highcharts.dateFormat(dateFormat, this.x)
        return `${dateStr}<br/><span style="color:${this.color}">\u25CF</span> ${this.series.name}: <b>${this.y.toFixed(0)}°</b>`
      }
    },
    plotOptions: {
      scatter: {
        marker: {
          enabled: true,
          radius: 2,
          states: {
            hover: {
              enabled: true,
              radius: 3
            }
          }
        }
      }
    },
    yAxis: {
      ...getCommonOptions().yAxis,
      title: { text: null },
      min: 0,
      max: 360,
      tickInterval: 45,
      labels: {
        formatter: function() {
          const directions = {
            0: 'N', 45: 'NO', 90: 'O', 135: 'SO',
            180: 'S', 225: 'SW', 270: 'W', 315: 'NW', 360: 'N'
          }
          return directions[this.value] || ''
        }
      }
    },
    series: [{
      name: 'Windrichtung',
      data: sortedData.filter(item => item.wind_dir != null).map(item => [new Date(item.datetime).getTime(), item.wind_dir]),
      color: 'rgb(54, 162, 235)',
      type: 'scatter'
    }]
  }), [sortedData, timeRange])

  // Aktuellste Werte für Übersicht (immer aus den 24h-Daten, Fallback auf sortedData)
  const current = (sortedCurrentData.length > 0 ? sortedCurrentData[sortedCurrentData.length - 1] : sortedData[sortedData.length - 1]) || {}

  // Berechne Min/Max für den gewählten Zeitraum
  const periodStats = useMemo(() => {
    // Für den gewählten Zeitraum alle Daten verwenden
    const periodData = sortedData

    if (periodData.length === 0) {
      return { 
        minTemp: null, maxTemp: null, minTempTime: null, maxTempTime: null,
        minHumidity: null, maxHumidity: null, minHumidityTime: null, maxHumidityTime: null,
        minPressure: null, maxPressure: null, minPressureTime: null, maxPressureTime: null
      }
    }
    
    const isCustomRange = typeof timeRange === 'object' && timeRange.type === 'custom'
    const customDays = isCustomRange ? (timeRange.days || 1) : 0
    const is24h = timeRange === '24h' || (isCustomRange && customDays < 7)
    const timeFormat = is24h ? 'HH:mm' : 'dd.MM HH:mm'

    // Gibt die anzuzeigende Zeit zurück: bei aggregierten Daten das spezifische *_time-Feld,
    // bei Rohdaten (24h) das datetime des Datenpunkts selbst.
    const itemTime = (item, timeField) => {
      if (!item) return null
      const raw = item[timeField] ?? item.datetime
      return format(new Date(raw), timeFormat, { locale: de })
    }

    // Bei aggregierten Daten (7d+) liegen echte Tages-Min/Max in eigenen Feldern;
    // bei 24h-Rohdaten sind diese Felder nicht vorhanden → Fallback auf den Messwert selbst.
    const hasAggregated = periodData[0]?.min_temperature != null

    // Temperatur
    const minTempField = hasAggregated ? 'min_temperature' : 'temperature'
    const maxTempField = hasAggregated ? 'max_temperature' : 'temperature'
    const minTempItem = periodData.reduce((min, item) =>
      item[minTempField] != null && (min === null || item[minTempField] < min[minTempField]) ? item : min, null)
    const maxTempItem = periodData.reduce((max, item) =>
      item[maxTempField] != null && (max === null || item[maxTempField] > max[maxTempField]) ? item : max, null)

    // Luftfeuchtigkeit
    const minHumidityField = hasAggregated ? 'min_humidity' : 'humidity'
    const maxHumidityField = hasAggregated ? 'max_humidity' : 'humidity'
    const minHumidityItem = periodData.reduce((min, item) =>
      item[minHumidityField] != null && (min === null || item[minHumidityField] < min[minHumidityField]) ? item : min, null)
    const maxHumidityItem = periodData.reduce((max, item) =>
      item[maxHumidityField] != null && (max === null || item[maxHumidityField] > max[maxHumidityField]) ? item : max, null)

    // Luftdruck
    const minPressureField = hasAggregated ? 'min_pressure' : 'pressure'
    const maxPressureField = hasAggregated ? 'max_pressure' : 'pressure'
    const minPressureItem = periodData.reduce((min, item) =>
      item[minPressureField] != null && (min === null || item[minPressureField] < min[minPressureField]) ? item : min, null)
    const maxPressureItem = periodData.reduce((max, item) =>
      item[maxPressureField] != null && (max === null || item[maxPressureField] > max[maxPressureField]) ? item : max, null)

    // Wind
    const maxWindGustItem = periodData.reduce((max, item) =>
      item.wind_gust != null && (max === null || item.wind_gust > max.wind_gust) ? item : max, null)

    return {
      minTemp: minTempItem?.[minTempField] ?? null,
      maxTemp: maxTempItem?.[maxTempField] ?? null,
      minTempTime: itemTime(minTempItem, 'min_temperature_time'),
      maxTempTime: itemTime(maxTempItem, 'max_temperature_time'),
      minHumidity: minHumidityItem?.[minHumidityField] ?? null,
      maxHumidity: maxHumidityItem?.[maxHumidityField] ?? null,
      minHumidityTime: itemTime(minHumidityItem, 'min_humidity_time'),
      maxHumidityTime: itemTime(maxHumidityItem, 'max_humidity_time'),
      minPressure: minPressureItem?.[minPressureField] ?? null,
      maxPressure: maxPressureItem?.[maxPressureField] ?? null,
      minPressureTime: itemTime(minPressureItem, 'min_pressure_time'),
      maxPressureTime: itemTime(maxPressureItem, 'max_pressure_time'),
      maxWindGust: maxWindGustItem?.wind_gust ?? null,
      maxWindGustTime: itemTime(maxWindGustItem, 'max_wind_gust_time'),
    }
  }, [sortedData, timeRange])        

  // Regen-Lookup: date-string → total_rain
  const rainByDate = useMemo(() => {
    const map = {}
    rainData.forEach(item => {
      const key = item.date
        ? item.date.split('T')[0]
        : item.week_start
          ? item.week_start.split('T')[0]
          : null
      if (key) map[key] = item.total_rain
    })
    return map
  }, [rainData])

  // Tabellen-Daten: ein Eintrag pro Tag
  const tableData = useMemo(() => {
    const isCustomRange = typeof timeRange === 'object' && timeRange.type === 'custom'
    const customDays = isCustomRange ? (timeRange.days || 1) : 0
    const isDailyAggregated =
      ['7d', '30d', '365d'].includes(timeRange) || (isCustomRange && customDays >= 7)

    if (isDailyAggregated) {
      return sortedData.map(item => {
        const dateKey = item.datetime.split('T')[0]
        return {
          date: format(new Date(item.datetime), 'dd.MM.yyyy', { locale: de }),
          tempMin: item.min_temperature ?? null,
          tempMax: item.max_temperature ?? null,
          humMin: item.min_humidity ?? null,
          humMax: item.max_humidity ?? null,
          pressMin: item.min_pressure ?? null,
          pressMax: item.max_pressure ?? null,
          rain: item.total_rain ?? rainByDate[dateKey] ?? null,
          windMax: item.wind_gust ?? null,
        }
      })
    } else {
      // Stundenwerte → pro Tag aggregieren
      const byDay = {}
      sortedData.forEach(item => {
        const d = new Date(item.datetime)
        const dateKey = format(d, 'yyyy-MM-dd')
        const dateLabel = format(d, 'dd.MM.yyyy', { locale: de })
        if (!byDay[dateKey]) {
          byDay[dateKey] = { date: dateLabel, temps: [], hums: [], pressures: [], rains: [], windGusts: [] }
        }
        if (item.temperature != null) byDay[dateKey].temps.push(item.temperature)
        if (item.humidity != null) byDay[dateKey].hums.push(item.humidity)
        if (item.pressure != null) byDay[dateKey].pressures.push(item.pressure)
        if (item.rain != null) byDay[dateKey].rains.push(item.rain)
        if (item.wind_gust != null) byDay[dateKey].windGusts.push(item.wind_gust)
      })
      const startKey = isCustomRange ? timeRange.start.split('T')[0] : null
      const endKey = isCustomRange ? timeRange.end.split('T')[0] : null
      return Object.entries(byDay)
        .sort(([a], [b]) => a.localeCompare(b))
        .filter(([k]) => !startKey || (k >= startKey && k <= endKey))
        .map(([, d]) => ({
          date: d.date,
          tempMin: d.temps.length ? Math.min(...d.temps) : null,
          tempMax: d.temps.length ? Math.max(...d.temps) : null,
          humMin: d.hums.length ? Math.round(Math.min(...d.hums)) : null,
          humMax: d.hums.length ? Math.round(Math.max(...d.hums)) : null,
          pressMin: d.pressures.length ? Math.min(...d.pressures) : null,
          pressMax: d.pressures.length ? Math.max(...d.pressures) : null,
          rain: d.rains.length ? Math.max(...d.rains) : null,
          windMax: d.windGusts.length ? Math.max(...d.windGusts) : null,
        }))
    }
  }, [sortedData, rainByDate, timeRange])

  return (
    <div className="dashboard">
      {/* Navigation für Zeitraum-Auswahl */}
      <div className="time-range-nav">
        <button 
          className={timeRange === '24h' ? 'active' : ''}
          onClick={() => onTimeRangeChange('24h')}
        >
          <span className="time-range-full">24 Stunden</span>
          <span className="time-range-short">24h</span>
        </button>
        <button 
          className={timeRange === '7d' ? 'active' : ''}
          onClick={() => onTimeRangeChange('7d')}
        >
          <span className="time-range-full">7 Tage</span>
          <span className="time-range-short">7d</span>
        </button>
        <button 
          className={timeRange === '30d' ? 'active' : ''}
          onClick={() => onTimeRangeChange('30d')}
        >
          <span className="time-range-full">30 Tage</span>
          <span className="time-range-short">30d</span>
        </button>
        <button 
          className={timeRange === '365d' ? 'active' : ''}
          onClick={() => onTimeRangeChange('365d')}
        >
          <span className="time-range-full">365 Tage</span>
          <span className="time-range-short">365d</span>
        </button>
        <button 
          className={(typeof timeRange === 'object' && timeRange.type === 'custom') ? 'active' : ''}
          onClick={handleOpenCustomRange}
        >
          <span className="time-range-full">Bereich</span>
          <span className="time-range-short">Bereich</span>
        </button>
        <button
          className={`table-toggle-btn${showTable ? ' active' : ''}`}
          onClick={onToggleTable}
        >
          <span>{showTable ? 'Grafik' : 'Tabelle'}</span>
        </button>
      </div>
      
      {/* Zeitraum-Beschreibung */}
      <div className="time-range-label">
        {timeRangeLabel}
      </div>
      
      {/* Charts Grid / Tabellenansicht */}
      {showTable ? (
        <div className="table-view">
          <div className="table-actions no-print">
            <button className="btn-print" onClick={() => window.print()}>🖨️ Drucken</button>
          </div>
          <table className="weather-table">
            <thead>
              <tr>
                <th rowSpan={2}>Datum</th>
                <th colSpan={2}>Temperatur<br/>°C</th>
                <th colSpan={2}>Feuchte<br/>%</th>
                <th colSpan={2}>Luftdruck<br/>hPa</th>
                <th rowSpan={2}>Regen<br/>mm</th>
                <th rowSpan={2}>Wind-V<br/>max km/h</th>
              </tr>
              <tr>
                <th>min</th>
                <th>max</th>
                <th>min</th>
                <th>max</th>
                <th>min</th>
                <th>max</th>
              </tr>
            </thead>
            <tbody>
              {tableData.map((row, i) => (
                <tr key={i}>
                  <td>{row.date}</td>
                  <td>{row.tempMin != null ? row.tempMin.toFixed(1) : '-'}</td>
                  <td>{row.tempMax != null ? row.tempMax.toFixed(1) : '-'}</td>
                  <td>{row.humMin != null ? row.humMin : '-'}</td>
                  <td>{row.humMax != null ? row.humMax : '-'}</td>
                  <td>{row.pressMin != null ? row.pressMin.toFixed(0) : '-'}</td>
                  <td>{row.pressMax != null ? row.pressMax.toFixed(0) : '-'}</td>
                  <td>{row.rain != null ? row.rain.toFixed(1) : '0'}</td>
                  <td>{row.windMax != null ? row.windMax.toFixed(1) : '-'}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      ) : (
      <div className="charts-grid">
        <div className="chart-item">
          <div className="current-value">Aktuell: {current.temperature?.toFixed(1) || '-'}°C</div>
          <div className="chart-container">
            <h3><span>🌡️ Temperatur{temperatureSuffix}</span><span className="unit">[°C]</span></h3>
            <div className="chart-wrapper">
              <HighchartsReact highcharts={Highcharts} options={temperatureOptions} />
            </div>
            <div className="chart-stats">
              Min: {periodStats.minTemp?.toFixed(1) || '-'}°C ({periodStats.minTempTime || '-'}) | Max: {periodStats.maxTemp?.toFixed(1) || '-'}°C ({periodStats.maxTempTime || '-'})
            </div>
          </div>
        </div>

        <div className="chart-item">
          <div className="current-value">Aktuell: {current.pressure?.toFixed(0) || '-'} hPa</div>
          <div className="chart-container">
            <h3><span>🌐 Luftdruck{aggregationSuffix}{(() => { const t = barTrendArrow(current.bar_trend); return t ? <span className="bar-trend" title={t.label}> {t.arrow}</span> : null })()}</span><span className="unit">[hPa]</span></h3>
            <div className="chart-wrapper">
              <HighchartsReact highcharts={Highcharts} options={pressureOptions} />
            </div>
            <div className="chart-stats">
              Min: {periodStats.minPressure?.toFixed(0) || '-'} hPa ({periodStats.minPressureTime || '-'}) | Max: {periodStats.maxPressure?.toFixed(0) || '-'} hPa ({periodStats.maxPressureTime || '-'})
            </div>
          </div>
        </div>

        <div className="chart-item">
          <div className="current-value">Aktuell: {current.humidity || '-'}%</div>
          <div className="chart-container">
            <h3><span>💧 Luftfeuchtigkeit{aggregationSuffix}</span><span className="unit">[%]</span></h3>
            <div className="chart-wrapper">
              <HighchartsReact highcharts={Highcharts} options={humidityOptions} />
            </div>
            <div className="chart-stats">
              Min: {periodStats.minHumidity || '-'}% ({periodStats.minHumidityTime || '-'}) | Max: {periodStats.maxHumidity || '-'}% ({periodStats.maxHumidityTime || '-'})
            </div>
          </div>
        </div>

        <div className="chart-item">
          <div className="current-value">Aktuell: {current.rain?.toFixed(1) || '-'} mm</div>
          <div className="chart-container">
            <h3><span>🌧️ Regen{rainSuffix}</span><span className="unit">[mm]</span></h3>
            <div className="chart-wrapper">
              <HighchartsReact highcharts={Highcharts} options={rainOptions} />
            </div>
            <div className="chart-stats"> </div>
          </div>
        </div>

        <div className="chart-item">
          <div className="current-value">Aktuell: {current.wind_dir ?? '-'}°</div>
          <div className="chart-container">
            <h3><span>🧭 Windrichtung{aggregationSuffix}</span><span className="unit">[°]</span></h3>
            <div className="chart-wrapper">
              <HighchartsReact highcharts={Highcharts} options={windDirOptions} />
            </div>
            <div className="chart-stats"> </div>
          </div>
        </div>

        <div className="chart-item">
          <div className="current-value">Aktuell: {current.wind_speed?.toFixed(1) || '-'} km/h</div>
          <div className="chart-container">
            <h3><span>💨 Wind{aggregationSuffix}</span><span className="unit">[km/h]</span></h3>
            <div className="chart-wrapper">
              <HighchartsReact highcharts={Highcharts} options={windSpeedOptions} />
            </div>
            <div className="chart-stats">
              Max: {periodStats.maxWindGust?.toFixed(1) || '-'} km/h ({periodStats.maxWindGustTime || '-'})
            </div>
          </div>
        </div>

      </div>
      )} {/* end showTable ternary */}

      {/* Modal Anleitung */}
      {showAnleitung && (
        <div className="modal-overlay" onClick={() => setShowAnleitung(false)}>
          <div className="anleitung-modal" onClick={(e) => e.stopPropagation()}>
            <div className="anleitung-modal-header">
              <span>Bedienungsanleitung</span>
              <button className="anleitung-modal-close" onClick={() => setShowAnleitung(false)}>✕</button>
            </div>
            <iframe
              src="/ANLEITUNG.html"
              title="Bedienungsanleitung"
              className="anleitung-frame"
            />
          </div>
        </div>
      )}

      {/* Modal für benutzerdefinierten Zeitbereich */}
      {showCustomRangeModal && (
        <div className="modal-overlay" onClick={handleCancelCustomRange}>
          <div className="modal-content" onClick={(e) => e.stopPropagation()}>
            <h2>Benutzerdefinierten Zeitbereich wählen</h2>
            
            <div className="modal-form">
              <div className="form-group">
                <label htmlFor="startDate">Startdatum:</label>
                <input
                  type="date"
                  id="startDate"
                  value={customStartDate}
                  onChange={(e) => setCustomStartDate(e.target.value)}
                />
              </div>
              
              <div className="form-group">
                <label htmlFor="endDate">Enddatum:</label>
                <input
                  type="date"
                  id="endDate"
                  value={customEndDate}
                  onChange={(e) => setCustomEndDate(e.target.value)}
                />
              </div>
              
              {customError && (
                <div className="error-message">{customError}</div>
              )}
              
              <div className="modal-info">
                <p>• Enddatum muss nach dem Startdatum liegen</p>
                <p>• Maximaler Zeitraum: 1 Jahr (365 Tage)</p>
              </div>
              
              <div className="modal-buttons">
                <button className="btn-cancel" onClick={handleCancelCustomRange}>
                  Abbrechen
                </button>
                <button className="btn-apply" onClick={handleApplyCustomRange}>
                  Anwenden
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Footer */}
      <div className="dashboard-footer">
        <div className="version-line">
          <div><a href="mailto:rxf@gmx.de">
                mailto:rxf@gmx.de
              </a>
          </div>
          <div>
            <button
              className="anleitung-btn"
              onClick={() => setShowAnleitung(true)}
            >
              Anleitung
            </button>
          </div>
          <div>
            <span className="version-full">Version</span>
            <span className="version-short">V</span>
            {' '}{version} – {buildDate}
          </div>
        </div>
        <hr className="footer-divider" />
        <div className="footer-credits">
          <div className="footer-left">Daten-Erfassung mit einer Davis VantagePro.</div>
          <div className="footer-right">Grafiken erzeugt mit HighCharts</div>
        </div>
      </div>

    </div>
  )
}

export default WeatherDashboard
