'use client'

import React, { useEffect, useState, useRef, useCallback } from 'react'

interface ForecastHour {
  time: string
  windspeed: number
  windgusts: number
  precipitation_probability: number
  cloudcover: number
  temperature: number
  weathercode: number
}

interface SpotForecastChartProps {
  lat: number
  lng: number
}

const TABS = [
  { label: 'Vento', key: 'wind' },
  { label: 'Chuva & Nuvens', key: 'rain' },
  { label: 'Temperatura', key: 'temp' },
] as const
type TabKey = typeof TABS[number]['key']

function sampleHourly(data: ForecastHour[], step = 3): ForecastHour[] {
  return data.filter((_, i) => i % step === 0)
}

function shortTime(time: string): string {
  const d = new Date(time)
  if (d.getHours() === 0) return d.toLocaleDateString('pt-PT', { weekday: 'short', day: 'numeric' })
  if (d.getHours() === 12) return '12h'
  return ''
}

function fullTime(time: string): string {
  const d = new Date(time)
  return d.toLocaleString('pt-PT', { weekday: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
}

// ── Legend ─────────────────────────────────────────────────────────────────────
interface LegendItem { color: string; label: string; dashed?: boolean }
function Legend({ items }: { items: LegendItem[] }) {
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px', marginTop: '8px', alignItems: 'center', fontFamily: 'sans-serif', fontSize: '11px', color: '#64748b' }}>
      {items.map((item) => (
        <span key={item.label} style={{ display: 'inline-flex', alignItems: 'center', gap: '5px', whiteSpace: 'nowrap' }}>
          {item.dashed ? (
            <span style={{ display: 'inline-block', width: '18px', height: '0', borderTop: `2px dashed ${item.color}`, flexShrink: 0 }} />
          ) : (
            <span style={{ display: 'inline-block', width: '10px', height: '10px', borderRadius: '50%', background: item.color, flexShrink: 0 }} />
          )}
          {item.label}
        </span>
      ))}
    </div>
  )
}

// ── Shared chart hook ──────────────────────────────────────────────────────────
interface UseChartHoverReturn {
  svgRef: React.RefObject<SVGSVGElement>
  wrapRef: React.RefObject<HTMLDivElement>
  hoverIdx: number | null
  tooltipStyle: React.CSSProperties
  onMouseMove: (e: React.MouseEvent<SVGSVGElement>) => void
  onMouseLeave: () => void
}

function useChartHover(
  n: number,
  PAD: { left: number; right: number },
  W: number
): UseChartHoverReturn {
  const svgRef = useRef<SVGSVGElement>(null)
  const wrapRef = useRef<HTMLDivElement>(null)
  const [hoverIdx, setHoverIdx] = useState<number | null>(null)
  const [tooltipStyle, setTooltipStyle] = useState<React.CSSProperties>({})

  const onMouseMove = useCallback(
    (e: React.MouseEvent<SVGSVGElement>) => {
      if (!svgRef.current) return
      const rect = svgRef.current.getBoundingClientRect()
      const relX = e.clientX - rect.left
      const innerW = rect.width - (PAD.left / W) * rect.width - (PAD.right / W) * rect.width
      const startX = (PAD.left / W) * rect.width
      const frac = Math.max(0, Math.min(1, (relX - startX) / innerW))
      const idx = Math.round(frac * (n - 1))
      setHoverIdx(idx)
      const tipX = rect.left + startX + frac * innerW - (wrapRef.current?.getBoundingClientRect().left ?? 0)
      const tipY = e.clientY - (wrapRef.current?.getBoundingClientRect().top ?? 0)
      setTooltipStyle({ left: tipX, top: tipY })
    },
    [n, PAD, W]
  )

  const onMouseLeave = useCallback(() => setHoverIdx(null), [])

  return { svgRef, wrapRef, hoverIdx, tooltipStyle, onMouseMove, onMouseLeave }
}

// ── Wind chart ─────────────────────────────────────────────────────────────────
function WindChart({ data }: { data: ForecastHour[] }) {
  const W = 560, H = 210
  const PAD = { top: 12, right: 14, bottom: 54, left: 46 }
  const innerW = W - PAD.left - PAD.right
  const innerH = H - PAD.top - PAD.bottom
  const n = data.length
  const maxVal = Math.ceil(Math.max(...data.map((d) => d.windgusts), 50) / 10) * 10
  const sx = (i: number) => PAD.left + (i / (n - 1)) * innerW
  const sy = (v: number) => PAD.top + innerH - (v / maxVal) * innerH

  const gustPath = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${sx(i).toFixed(1)},${sy(d.windgusts).toFixed(1)}`).join(' ')
  const windPath = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${sx(i).toFixed(1)},${sy(d.windspeed).toFixed(1)}`).join(' ')
  const gustArea = `${gustPath} L${sx(n - 1)},${PAD.top + innerH} L${sx(0)},${PAD.top + innerH} Z`
  const yTicks = Array.from({ length: Math.floor(maxVal / 10) + 1 }, (_, i) => i * 10).filter((v) => v <= maxVal)

  const { svgRef, wrapRef, hoverIdx, tooltipStyle, onMouseMove, onMouseLeave } = useChartHover(n, PAD, W)

  const d0 = hoverIdx !== null ? data[hoverIdx] : null

  return (
    <div className="fc-chart-wrap" ref={wrapRef}>
      {d0 && hoverIdx !== null && (
        <div className="fc-tooltip" style={tooltipStyle}>
          <div style={{ fontWeight: 700, marginBottom: 2 }}>{fullTime(d0.time)}</div>
          <div>💨 Vento: <strong>{d0.windspeed} km/h</strong></div>
          <div>🌬 Rajadas: <strong>{d0.windgusts} km/h</strong></div>
        </div>
      )}
      <svg
        ref={svgRef}
        viewBox={`0 0 ${W} ${H}`}
        className="fc-svg"
        onMouseMove={onMouseMove}
        onMouseLeave={onMouseLeave}
        style={{ cursor: 'crosshair' }}
      >
        {/* Grid + Y ticks */}
        {yTicks.map((v) => (
          <g key={v}>
            <line x1={PAD.left} y1={sy(v)} x2={W - PAD.right} y2={sy(v)} stroke="#e2e8f0" strokeWidth="1" />
            <text x={PAD.left - 5} y={sy(v) + 4} textAnchor="end" fontSize="10" fill="#94a3b8">{v}</text>
          </g>
        ))}
        <text x={8} y={PAD.top + innerH / 2} textAnchor="middle" fontSize="9" fill="#94a3b8" transform={`rotate(-90,8,${PAD.top + innerH / 2})`}>km/h</text>

        {/* Ref lines */}
        <line x1={PAD.left} y1={sy(30)} x2={W - PAD.right} y2={sy(30)} stroke="#f97316" strokeDasharray="5 3" strokeWidth="1.5" />
        <text x={W - PAD.right + 3} y={sy(30) + 4} fontSize="9" fill="#f97316">30</text>
        <line x1={PAD.left} y1={sy(40)} x2={W - PAD.right} y2={sy(40)} stroke="#dc2626" strokeDasharray="5 3" strokeWidth="1.5" />
        <text x={W - PAD.right + 3} y={sy(40) + 4} fontSize="9" fill="#dc2626">40</text>

        {/* Gust area + lines */}
        <path d={gustArea} fill="#fee2e2" opacity="0.65" />
        <path d={gustPath} fill="none" stroke="#f87171" strokeWidth="1.5" />
        <path d={windPath} fill="none" stroke="#0096FF" strokeWidth="2.5" />

        {/* Crosshair */}
        {hoverIdx !== null && (
          <>
            <line x1={sx(hoverIdx)} y1={PAD.top} x2={sx(hoverIdx)} y2={PAD.top + innerH} stroke="#334155" strokeWidth="1" strokeDasharray="3 2" opacity="0.5" />
            <circle cx={sx(hoverIdx)} cy={sy(data[hoverIdx].windspeed)} r="4" fill="#0096FF" stroke="#fff" strokeWidth="1.5" />
            <circle cx={sx(hoverIdx)} cy={sy(data[hoverIdx].windgusts)} r="4" fill="#f87171" stroke="#fff" strokeWidth="1.5" />
          </>
        )}

        {/* X axis */}
        {data.map((d, i) => {
          const label = shortTime(d.time)
          if (!label) return null
          return <text key={i} x={sx(i)} y={PAD.top + innerH + 8} textAnchor="end" fontSize="9" fill="#64748b" transform={`rotate(-35,${sx(i)},${PAD.top + innerH + 8})`}>{label}</text>
        })}
      </svg>
      <Legend items={[
        { color: '#0096FF', label: 'Vento' },
        { color: '#f87171', label: 'Rajadas' },
        { color: '#f97316', label: '30 km/h', dashed: true },
        { color: '#dc2626', label: '40 km/h', dashed: true },
      ]} />
    </div>
  )
}

// ── Rain chart ─────────────────────────────────────────────────────────────────
function RainChart({ data }: { data: ForecastHour[] }) {
  const W = 560, H = 200
  const PAD = { top: 12, right: 14, bottom: 54, left: 38 }
  const innerW = W - PAD.left - PAD.right
  const innerH = H - PAD.top - PAD.bottom
  const n = data.length
  const barW = Math.max(1, innerW / n - 1)
  const sx = (i: number) => PAD.left + (i / n) * innerW
  const sy = (v: number) => PAD.top + innerH - (v / 100) * innerH
  const cloudPath = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${(sx(i) + barW / 2).toFixed(1)},${sy(d.cloudcover).toFixed(1)}`).join(' ')

  const { svgRef, wrapRef, hoverIdx, tooltipStyle, onMouseMove, onMouseLeave } = useChartHover(n, PAD, W)
  const d0 = hoverIdx !== null ? data[hoverIdx] : null

  return (
    <div className="fc-chart-wrap" ref={wrapRef}>
      {d0 && hoverIdx !== null && (
        <div className="fc-tooltip" style={tooltipStyle}>
          <div style={{ fontWeight: 700, marginBottom: 2 }}>{fullTime(d0.time)}</div>
          <div>🌧 Chuva: <strong>{d0.precipitation_probability}%</strong></div>
          <div>☁️ Nuvens: <strong>{d0.cloudcover}%</strong></div>
        </div>
      )}
      <svg
        ref={svgRef}
        viewBox={`0 0 ${W} ${H}`}
        className="fc-svg"
        onMouseMove={onMouseMove}
        onMouseLeave={onMouseLeave}
        style={{ cursor: 'crosshair' }}
      >
        {[0, 25, 50, 75, 100].map((v) => (
          <g key={v}>
            <line x1={PAD.left} y1={sy(v)} x2={W - PAD.right} y2={sy(v)} stroke="#e2e8f0" strokeWidth="1" />
            <text x={PAD.left - 4} y={sy(v) + 4} textAnchor="end" fontSize="10" fill="#94a3b8">{v}</text>
          </g>
        ))}
        <text x={8} y={PAD.top + innerH / 2} textAnchor="middle" fontSize="9" fill="#94a3b8" transform={`rotate(-90,8,${PAD.top + innerH / 2})`}>%</text>

        {data.map((d, i) => {
          const bh = (d.precipitation_probability / 100) * innerH
          const active = hoverIdx === i
          return (
            <rect key={i} x={sx(i)} y={PAD.top + innerH - bh} width={barW} height={bh}
              fill="#60a5fa" opacity={active ? 1 : 0.7} rx="1" />
          )
        })}
        <path d={cloudPath} fill="none" stroke="#94a3b8" strokeWidth="2" strokeDasharray="5 3" />

        {hoverIdx !== null && (
          <>
            <line x1={sx(hoverIdx) + barW / 2} y1={PAD.top} x2={sx(hoverIdx) + barW / 2} y2={PAD.top + innerH} stroke="#334155" strokeWidth="1" strokeDasharray="3 2" opacity="0.4" />
            <circle cx={sx(hoverIdx) + barW / 2} cy={sy(data[hoverIdx].cloudcover)} r="4" fill="#94a3b8" stroke="#fff" strokeWidth="1.5" />
          </>
        )}

        {data.map((d, i) => {
          const label = shortTime(d.time)
          if (!label) return null
          const rx = sx(i) + barW / 2; const ry = PAD.top + innerH + 8
          return <text key={i} x={rx} y={ry} textAnchor="end" fontSize="9" fill="#64748b" transform={`rotate(-35,${rx},${ry})`}>{label}</text>
        })}
      </svg>
      <Legend items={[
        { color: '#60a5fa', label: 'Prob. chuva (%)' },
        { color: '#94a3b8', label: 'Cobertura nuvens (%)' },
      ]} />
    </div>
  )
}

// ── Temp chart ─────────────────────────────────────────────────────────────────
function TempChart({ data }: { data: ForecastHour[] }) {
  const W = 560, H = 200
  const PAD = { top: 12, right: 14, bottom: 54, left: 40 }
  const innerW = W - PAD.left - PAD.right
  const innerH = H - PAD.top - PAD.bottom
  const n = data.length
  const temps = data.map((d) => d.temperature)
  const minT = Math.floor(Math.min(...temps) / 5) * 5 - 2
  const maxT = Math.ceil(Math.max(...temps) / 5) * 5 + 2
  const range = maxT - minT
  const sx = (i: number) => PAD.left + (i / (n - 1)) * innerW
  const sy = (v: number) => PAD.top + innerH - ((v - minT) / range) * innerH
  const linePath = data.map((d, i) => `${i === 0 ? 'M' : 'L'}${sx(i).toFixed(1)},${sy(d.temperature).toFixed(1)}`).join(' ')
  const areaPath = `${linePath} L${sx(n - 1)},${PAD.top + innerH} L${sx(0)},${PAD.top + innerH} Z`
  const step = range > 20 ? 5 : range > 10 ? 2 : 1
  const yTicks: number[] = []
  for (let v = Math.ceil(minT / step) * step; v <= maxT; v += step) yTicks.push(v)

  const { svgRef, wrapRef, hoverIdx, tooltipStyle, onMouseMove, onMouseLeave } = useChartHover(n, PAD, W)
  const d0 = hoverIdx !== null ? data[hoverIdx] : null

  return (
    <div className="fc-chart-wrap" ref={wrapRef}>
      {d0 && hoverIdx !== null && (
        <div className="fc-tooltip" style={tooltipStyle}>
          <div style={{ fontWeight: 700, marginBottom: 2 }}>{fullTime(d0.time)}</div>
          <div>🌡 Temperatura: <strong>{d0.temperature}°C</strong></div>
        </div>
      )}
      <svg
        ref={svgRef}
        viewBox={`0 0 ${W} ${H}`}
        className="fc-svg"
        onMouseMove={onMouseMove}
        onMouseLeave={onMouseLeave}
        style={{ cursor: 'crosshair' }}
      >
        {yTicks.map((v) => (
          <g key={v}>
            <line x1={PAD.left} y1={sy(v)} x2={W - PAD.right} y2={sy(v)} stroke="#e2e8f0" strokeWidth="1" />
            <text x={PAD.left - 4} y={sy(v) + 4} textAnchor="end" fontSize="10" fill="#94a3b8">{v}</text>
          </g>
        ))}
        <text x={8} y={PAD.top + innerH / 2} textAnchor="middle" fontSize="9" fill="#94a3b8" transform={`rotate(-90,8,${PAD.top + innerH / 2})`}>°C</text>

        <path d={areaPath} fill="#fef3c7" opacity="0.7" />
        <path d={linePath} fill="none" stroke="#f59e0b" strokeWidth="2.5" />

        {hoverIdx !== null && (
          <>
            <line x1={sx(hoverIdx)} y1={PAD.top} x2={sx(hoverIdx)} y2={PAD.top + innerH} stroke="#334155" strokeWidth="1" strokeDasharray="3 2" opacity="0.5" />
            <circle cx={sx(hoverIdx)} cy={sy(data[hoverIdx].temperature)} r="4" fill="#f59e0b" stroke="#fff" strokeWidth="1.5" />
          </>
        )}

        {data.map((d, i) => {
          const label = shortTime(d.time)
          if (!label) return null
          return <text key={i} x={sx(i)} y={PAD.top + innerH + 8} textAnchor="end" fontSize="9" fill="#64748b" transform={`rotate(-35,${sx(i)},${PAD.top + innerH + 8})`}>{label}</text>
        })}
      </svg>
      <Legend items={[
        { color: '#f59e0b', label: 'Temperatura (°C)' },
      ]} />
    </div>
  )
}

// ── Main component ─────────────────────────────────────────────────────────────
export function SpotForecastChart({ lat, lng }: SpotForecastChartProps) {
  const [data, setData] = useState<ForecastHour[] | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(false)
  const [tab, setTab] = useState<TabKey>('wind')

  useEffect(() => {
    fetch(`/api/weather/forecast?lat=${lat}&lng=${lng}`)
      .then((r) => r.json())
      .then((json) => {
        if (json.error || !json.hourly) setError(true)
        else setData(sampleHourly(json.hourly, 3))
      })
      .catch(() => setError(true))
      .finally(() => setLoading(false))
  }, [lat, lng])

  if (loading) return <div className="forecast-loading">A carregar previsão…</div>
  if (error || !data) return <div className="forecast-error">Previsão indisponível</div>

  return (
    <div className="forecast-wrap">
      <div className="forecast-tabs">
        {TABS.map((t) => (
          <button key={t.key} className={`forecast-tab${tab === t.key ? ' active' : ''}`} onClick={() => setTab(t.key)}>
            {t.label}
          </button>
        ))}
      </div>

      <div className="forecast-chart-box">
        {tab === 'wind' && <><p className="forecast-hint">Passa o rato para ver valores · laranja = 30 km/h · vermelho = 40 km/h</p><WindChart data={data} /></>}
        {tab === 'rain' && <><p className="forecast-hint">Passa o rato para ver valores · barras = chuva · linha = nuvens</p><RainChart data={data} /></>}
        {tab === 'temp' && <><p className="forecast-hint">Passa o rato para ver valores · temperatura ao nível do solo</p><TempChart data={data} /></>}
      </div>

      <p className="forecast-source">Fonte: Open-Meteo · previsão atualizada a cada hora</p>
    </div>
  )
}
