/* SolarDose — uygulama akışı: Hesaplama formu → Enstrüman saati */
const { useState, useEffect, useRef, useMemo } = React;

const LANG = {
  tr: {
    navCalc: 'HESAPLAYICI', navSci: 'BİLİM', navFaq: 'SSS', navAbout: 'HAKKINDA',
    h1a: 'D vitamini için ne zaman', h1b: 'güneşe çıkmalısın?',
    lede: 'Güneş her saat D vitamini üretmez. Konumuna, mevsimine ve deri tipine göre senin için doğru pencereyi hesaplıyoruz.',
    loc: 'Konum', useLoc: 'KONUMUMU KULLAN', date: 'Tarih', today: 'Bugün',
    skin: 'Deri Tipi', skinHint: 'Fitzpatrick ölçeği', exposed: 'Açık Vücut Yüzeyi',
    calc: 'HESAPLA', recalc: 'YENİDEN HESAPLA', back: 'GERİ',
    recommended: 'ŞU AN ÖNERİLEN', minute: 'DAKİKA', minuteLong: 'dakika',
    nowClosed: 'Şu an güneş çok alçak', nowNight: 'Şu an gece',
    closedSub: 'Anlık sentez yok — pik nota bak ↓',
    peakNote: 'En verimli pencere', windowLbl: 'Pik pencere', noWindow: 'Pencere yok',
    factors: 'Faktörler', dayArc: 'Bugünkü güneş yörüngesi',
    start: 'Başlangıç', end: 'Bitiş', now: 'ŞİMDİ',
    scrub: 'Saati kaydır', disclaimer: 'Tahminî değerler · tıbbi tavsiye değildir',
  },
  en: {
    navCalc: 'CALCULATOR', navSci: 'SCIENCE', navFaq: 'FAQ', navAbout: 'ABOUT',
    h1a: 'When to catch the sun', h1b: 'for vitamin D?',
    lede: 'The sun doesn\u2019t make vitamin D every hour. We calculate the right window for you \u2014 based on your location, season, and skin type.',
    loc: 'Location', useLoc: 'USE MY LOCATION', date: 'Date', today: 'Today',
    skin: 'Skin Type', skinHint: 'Fitzpatrick scale', exposed: 'Exposed Body Area',
    calc: 'CALCULATE', recalc: 'RECALCULATE', back: 'BACK',
    recommended: 'RECOMMENDED NOW', minute: 'MINUTES', minuteLong: 'minutes',
    nowClosed: 'Sun too low right now', nowNight: 'It\u2019s night now',
    closedSub: 'No synthesis now — see peak note ↓',
    peakNote: 'Most efficient window', windowLbl: 'Peak window', noWindow: 'No window',
    factors: 'Factors', dayArc: 'Today\u2019s solar arc',
    start: 'Start', end: 'End', now: 'NOW',
    scrub: 'Scrub time', disclaimer: 'Estimated values · not medical advice',
  },
};

function LocationInput({ loc, onSelect, t, lang }) {
  const [query, setQuery] = React.useState(loc.name || '');
  const [suggestions, setSuggestions] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const debounceRef = React.useRef(null);
  const isSelectedRef = React.useRef(!!loc.name);

  // Dışarıdan loc değişince (Konumumu Kullan) input'u güncelle
  React.useEffect(() => {
    if (loc.name) {
      setQuery(loc.name);
      isSelectedRef.current = true;
    }
  }, [loc.name]);

  const search = (val) => {
    setQuery(val);
    isSelectedRef.current = false;
    if (debounceRef.current) clearTimeout(debounceRef.current);
    if (val.length < 3) { setSuggestions([]); return; }
    debounceRef.current = setTimeout(async () => {
      setLoading(true);
      try {
        const res = await fetch(
          `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(val)}&format=json&limit=5&addressdetails=1`,
          { headers: { 'Accept-Language': lang === 'tr' ? 'tr,en' : 'en' } }
        );
        const data = await res.json();
        setSuggestions(data.map((r) => ({
          name: (() => {
            const city = r.address?.city || r.address?.town || r.address?.village || r.address?.county || r.display_name.split(',')[0].trim();
            const country = r.address?.country || '';
            return country ? `${city}, ${country}` : city;
          })(),
          lat: parseFloat(r.lat),
          lon: parseFloat(r.lon),
          alt: 0,
          tz: Math.round(parseFloat(r.lon) / 15),
        })));
      } catch (e) {
        setSuggestions([]);
      } finally {
        setLoading(false);
      }
    }, 400);
  };

  const select = (s) => {
    setQuery(s.name);
    setSuggestions([]);
    isSelectedRef.current = true;
    onSelect(s);
  };

  const handleBlur = () => {
    // Öneri tıklaması için kısa gecikme
    setTimeout(() => setSuggestions([]), 150);
    // Seçim yapılmadıysa input'u temizle
    if (!isSelectedRef.current) {
      setQuery('');
      setSuggestions([]);
    }
  };

  return (
    <div style={{ position: 'relative' }}>
      <div style={{
        position: 'relative',
        background: 'var(--ink2)',
        border: '1px solid var(--line)',
        borderRadius: '8px',
      }}>
        <input
          type="text"
          value={query}
          onChange={(e) => search(e.target.value)}
          onBlur={handleBlur}
          placeholder={t.loc === 'Konum' ? 'Konum girin...' : 'Enter location...'}
          style={{
            width: '100%', background: 'transparent', border: 'none',
            fontFamily: SDT.mono, fontSize: 15, color: SDT.text,
            padding: '14px 16px', outline: 'none', boxSizing: 'border-box',
          }}
        />
        {loading && (
          <span style={{ position: 'absolute', right: 16, top: '50%', transform: 'translateY(-50%)', fontFamily: SDT.mono, fontSize: 10, color: SDT.mute2 }}>…</span>
        )}
      </div>
      {suggestions.length > 0 && (
        <div style={{
          position: 'absolute', top: '100%', left: 0, right: 0, zIndex: 100,
          background: 'var(--ink2)', border: '1px solid var(--line)',
          borderTop: 'none', borderRadius: '0 0 8px 8px',
          boxShadow: '0 8px 24px rgba(0,0,0,0.10)',
        }}>
          {suggestions.map((s, i) => (
            <div key={i} onMouseDown={() => select(s)} style={{
              padding: '12px 16px', cursor: 'pointer', fontFamily: SDT.mono,
              fontSize: 13, color: SDT.text,
              borderTop: i > 0 ? '1px solid var(--line)' : 'none',
            }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(51,39,26,0.06)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}
            >
              {s.name}
            </div>
          ))}
        </div>
      )}
      {loc.name && loc.lat !== 0 && (
        <span className="coords" style={{ display: 'block', marginTop: 8 }}>
          {loc.lat.toFixed(2)}°N · {loc.lon.toFixed(2)}°E · {loc.alt} m
        </span>
      )}
    </div>
  );
}

/* ── Hesaplama formu ── */
function InputScreen({ state, set, onCalc, t, lang, setLang, nav }) {
  const loc = state.loc;
  return (
    <div className="screen input-screen">
      <TopNav page="calc" nav={nav} lang={lang} setLang={setLang} t={t} />

      <div className="input-body">
        <div className="input-grid">
          <div className="input-intro">
            <h1>{t.h1a}<br /><span className="ital">{t.h1b}</span></h1>
            <p>{t.lede}</p>
            <div className="formula-tag">
              <Mono s={10} c={SDT.mute2}>α ≥ 35° · UVB 290–315 nm → D₃</Mono>
            </div>
          </div>

          <div className="input-fields">
            {/* Konum */}
            <div className="field">
              <div className="field-head"><Mono s={10}>01 · {t.loc}</Mono>
                <button className="ghost-btn" onClick={() => set({ geo: true })}>↻ {t.useLoc}</button>
              </div>
              <LocationInput loc={loc} onSelect={(l) => set({ loc: l })} t={t} lang={lang} />
            </div>

            {/* Tarih */}
            <div className="field">
              <div className="field-head"><Mono s={10}>02 · {t.date}</Mono></div>
              <div className="date-row">
                <span className="date-val">{state.date.toLocaleDateString(lang === 'tr' ? 'tr-TR' : 'en-US', { day: 'numeric', month: 'long', year: 'numeric' })}</span>
                <span className="today-pill">{t.today}</span>
              </div>
            </div>

            {/* Deri tipi */}
            <div className="field">
              <div className="field-head"><Mono s={10}>03 · {t.skin}</Mono>
                <Mono s={10} c={SDT.text}>{lang === 'tr' ? 'TİP' : 'TYPE'} {SD.SKIN[state.skin - 1].roman} · {lang === 'tr' ? SD.SKIN[state.skin - 1].name : SD.SKIN[state.skin - 1].nameEn}</Mono>
              </div>
              <FitzRow value={state.skin} onChange={(id) => set({ skin: id })} size={40} gap={14} />
              <p className="field-desc">{lang === 'tr' ? SD.SKIN[state.skin - 1].desc : SD.SKIN[state.skin - 1].descEn}</p>
            </div>

            {/* BSA */}
            <div className="field">
              <div className="field-head"><Mono s={10}>04 · {t.exposed}</Mono>
                <Mono s={10} c={SDT.text}>%{state.bsa}</Mono>
              </div>
              <div className="bsa-row">
                {SD.BSA.map((b) => (
                  <button key={b.pct} className={'bsa-opt' + (state.bsa === b.pct ? ' on' : '')} onClick={() => set({ bsa: b.pct })}>
                    <span className="bsa-pct">%{b.pct}</span>
                    <span className="bsa-lbl">{lang === 'tr' ? b.label : b.labelEn}</span>
                  </button>
                ))}
              </div>
            </div>

            <button className="calc-btn" onClick={onCalc}>{t.calc} <span>→</span></button>
          </div>
        </div>
      </div>

      <footer className="botbar">
        <Mono s={10} c={SDT.mute2}>{t.disclaimer}</Mono>
        <Mono s={10} c={SDT.mute2}>SOLARDOSE.APP</Mono>
      </footer>
    </div>
  );
}

/* ── Sonuç: enstrüman saati ── */
function ResultScreen({ state, onBack, onRecalc, t, lang, setLang, nav }) {
  const loc = state.loc;
  const cloud = state.cloud;
  const skinFactor = SD.SKIN[state.skin - 1].factor;

  const profile = useMemo(
    () => SD.dayProfile(loc, state.date, skinFactor, state.bsa, cloud),
    [loc, state.date, skinFactor, state.bsa, cloud]
  );

  // Lokasyonun saat diliminde gece yarısı → UTC
  const tz = loc.tz ?? 0;
  const tzMs = tz * 3600000;

  // Seçilen lokasyonun şu anki yerel saati (dakika cinsinden)
  const locNowMin = (() => {
    const d = new Date(Date.now() + tz * 3600000);
    return d.getUTCHours() * 60 + d.getUTCMinutes();
  })();
  console.log('[LOC] tz:', tz, 'locNowMin:', locNowMin, '->', SD.minToClock(locNowMin));

  const noonLocal = new Date(profile.noon.getTime() + tzMs);
  const noonMin = noonLocal.getUTCHours() * 60 + noonLocal.getUTCMinutes();

  const [markMin, setMarkMin] = useState(locNowMin);

  // markDate: lokasyonun gece yarısı + markMin dakika (UTC cinsinden)
  const markDate = useMemo(() => {
    const day0 = new Date(Date.UTC(state.date.getFullYear(), state.date.getMonth(), state.date.getDate()) - tzMs);
    return new Date(day0.getTime() + markMin * 60000);
  }, [markMin, state.date, tzMs]);

  const inst = SD.instant(loc, markDate, skinFactor, state.bsa, cloud);
  const isNow = Math.abs(markMin - locNowMin) <= 2;
  const peakMin = profile.peakMin;

  // büyük rakam
  const bigVal = inst.open && inst.min ? Math.round(inst.min) : null;
  // Rakamlar orantılı genişlikte olduğundan (Figtree'de tabular yok), çok haneli
  // sayılar optik olarak kayar. Gerçek mürekkep kutusunu ölçüp tam ortalarız.
  const bigRef = useRef(null);
  useEffect(() => {
    const el = bigRef.current;
    if (!el) return;
    const center = () => {
      if (!bigRef.current) return;
      el.style.transform = 'none';
      const cs = getComputedStyle(el);
      const cv = window.__sdNumCv || (window.__sdNumCv = document.createElement('canvas'));
      const ctx = cv.getContext('2d');
      ctx.font = cs.fontWeight + ' ' + cs.fontSize + ' ' + cs.fontFamily;
      if ('letterSpacing' in ctx) ctx.letterSpacing = cs.letterSpacing;
      const m = ctx.measureText(el.textContent);
      const off = (m.actualBoundingBoxRight - m.actualBoundingBoxLeft) / 2 - m.width / 2;
      el.style.transform = 'translateX(' + (-off).toFixed(2) + 'px)';
    };
    center();
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(center);
  }, [bigVal]);
  const factors = [
    [lang === 'tr' ? 'Güneş α' : 'Sun α', `${Math.max(0, inst.alt).toFixed(0)}°`],
    ['UV', inst.uv.toFixed(1)],
    [lang === 'tr' ? 'Bulut' : 'Cloud', `%${cloud}`],
    [lang === 'tr' ? 'Rakım' : 'Altitude', `${loc.alt}m`],
    [lang === 'tr' ? 'BSA' : 'BSA', `%${state.bsa}`],
  ];

  return (
    <div className="screen result-screen">
      <TopNav page="calc" nav={nav} lang={lang} setLang={setLang} t={t} />
      <header className="topbar">
        <button className="ghost-btn back" onClick={onBack}>← {t.back}</button>
        <div className="result-loc">
          <span className="rl-city">{loc.name}</span>
          <Mono s={10} c={SDT.mute} style={{ marginTop: 2 }}>{state.date.toLocaleDateString(lang === 'tr' ? 'tr-TR' : 'en-US', { day: 'numeric', month: 'short' })} · {loc.lat.toFixed(1)}°N · {loc.alt}m</Mono>
        </div>
        <button className="ghost-btn" onClick={onRecalc}>↻ {t.recalc}</button>
      </header>

      <div className="result-body">
        {/* Sol: faktörler (masaüstü) */}
        <aside className="rail rail-left">
          <Mono s={10} style={{ marginBottom: 14 }}>{t.factors}</Mono>
          <div className="factor-list">
            {factors.map(([k, v]) => (
              <div className="factor" key={k}><span>{k}</span><b>{v}</b></div>
            ))}
          </div>
          <div className="skin-mini">
            <Mono s={10} style={{ marginBottom: 10 }}>{t.skin}</Mono>
            <div className="skin-mini-row">
              <span className="swatch" style={{ background: SD.SKIN[state.skin - 1].color }} />
              <span>Tip {SD.SKIN[state.skin - 1].roman} · {SD.SKIN[state.skin - 1].name}</span>
            </div>
          </div>
        </aside>

        {/* Orta: kadran */}
        <div className="dial-zone">
          <div className="dial-wrap">
            <DialInstrument profile={profile} loc={loc} markerDate={markDate} />
            <div className="dial-center">
              <Mono s={10} c={SDT.mute} style={{ marginBottom: 6 }}>
                {isNow ? t.recommended : SD.fmtClockTz(markDate, loc.tz)}
              </Mono>
              {bigVal !== null ? (
                <>
                  <div className="big-num" ref={bigRef}>{String(bigVal)}</div>
                  <Mono s={12} c={SDT.mute} ls="0.2em" style={{ marginTop: 4 }}>{t.minute}</Mono>
                  <div className="iu-pill">≈ {SD.TARGET_IU} IU D3</div>
                </>
              ) : (
                <>
                  <div className="closed-icon">○</div>
                  <div className="closed-txt">{inst.daylight ? t.nowClosed : t.nowNight}</div>
                  <Mono s={10} c={SDT.mute2} style={{ marginTop: 8, textAlign: 'center', maxWidth: 180 }}>{t.closedSub}</Mono>
                </>
              )}
            </div>
          </div>

          {/* saat kaydırıcı */}
          <div className="scrubber">
            <div className="scrub-head">
              <Mono s={9} c={SDT.mute2}>{t.scrub}</Mono>
              <Mono s={10} c={isNow ? 'var(--accent)' : SDT.text}>{isNow ? t.now + ' · ' : ''}{SD.minToClock(markMin)}</Mono>
            </div>
            <input type="range" min="240" max="1320" step="2" value={markMin} onChange={(e) => setMarkMin(+e.target.value)} />
          </div>
        </div>

        {/* Sağ: pik not + gün yörüngesi */}
        <aside className="rail rail-right">
          <div className="peak-card">
            <Mono s={10} c="var(--accent)" style={{ marginBottom: 12 }}>★ {t.peakNote}</Mono>
            {profile.hasWindow ? (
              <>
                <div className="peak-window">
                  <span>{SD.fmtClockTz(profile.peakStart, loc.tz)}</span>
                  <span className="pw-dash" />
                  <span>{SD.fmtClockTz(profile.peakEnd, loc.tz)}</span>
                </div>
                <Mono s={9} c={SDT.mute2} style={{ marginBottom: 14 }}>{t.windowLbl} · ±30 {lang === 'tr' ? 'dk' : 'min'}</Mono>
                <p className="peak-text">
                  {lang === 'tr' ? (
                    <>Bu saatler arasında güneş en dik açıda — <b>sadece {Math.round(peakMin)} dakika</b> yeterli.</>
                  ) : (
                    <>These are the steepest-sun hours — <b>just {Math.round(peakMin)} minutes</b> is enough.</>
                  )}
                </p>
              </>
            ) : (
              <p className="peak-text">{lang === 'tr'
                ? 'Bugün güneş D vitamini için yeterince yükselmiyor. Takviye düşünebilirsin.'
                : 'The sun doesn\u2019t rise high enough for vitamin D today. Consider a supplement.'}</p>
            )}
          </div>

          <div className="arc-card">
            <Mono s={10} style={{ marginBottom: 10 }}>{t.dayArc}</Mono>
            <DayStrip profile={profile} loc={loc} markerDate={markDate} />
          </div>
        </aside>
      </div>

      <footer className="botbar">
        <Mono s={10} c={SDT.mute2}>{t.disclaimer}</Mono>
        <Mono s={10} c={SDT.mute2}>SUNCALC · HOLICK 2004</Mono>
      </footer>
    </div>
  );
}

function App() {
  const [lang, setLangState] = useState(() => localStorage.getItem('sd_lang') || 'tr');
  function setLang(l) { setLangState(l); localStorage.setItem('sd_lang', l); }
  const [page, setPage] = useState('calc'); // calc | about | science | faq
  const [view, setView] = useState('input'); // input | result
  const [anim, setAnim] = useState(false);
  const [state, setState] = useState({
    loc: { name: '', lat: 0, lon: 0, alt: 0, tz: 0 },
    date: new Date(),
    skin: 3,
    bsa: 25,
    cloud: 12,
    geo: false,
  });
  const t = LANG[lang];
  const set = (patch) => setState((s) => ({ ...s, ...patch }));

  // URL parametrelerinden konum oku
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const lat = parseFloat(params.get('lat'));
    const lon = parseFloat(params.get('lon'));
    const tz = parseInt(params.get('tz'));
    const name = params.get('name');
    const langParam = params.get('lang');
    if (langParam === 'en' || langParam === 'tr') {
      setLang(langParam);
    }
    if (lat && lon && name) {
      // Küçük gecikme: Open-Meteo effect'in üzerine yazmasını bekle
      setTimeout(() => {
        set({ loc: { name, lat, lon, alt: 0, tz: tz || Math.round(lon / 15) } });
        window.history.replaceState({}, '', '/');
      }, 800);
    }
  }, []);

  // Konum değişince Open-Meteo'dan rakım, bulut ve timezone al
  useEffect(() => {
    if (!state.loc.lat || !state.loc.lon) return;
    fetch(`https://api.open-meteo.com/v1/forecast?latitude=${state.loc.lat}&longitude=${state.loc.lon}&current=cloud_cover&timezone=auto&forecast_days=1`)
      .then(r => r.json())
      .then(data => {
        const tz = Math.round((data.utc_offset_seconds || 0) / 3600);
        const alt = Math.round(data.elevation || 0);
        const cloud = data.current?.cloud_cover ?? 12;
        set({
          cloud,
          loc: { ...state.loc, tz, alt },
        });
      })
      .catch(() => {});
  }, [state.loc.lat, state.loc.lon]);

  // geolocation
  useEffect(() => {
    if (!state.geo) return;
    set({ geo: false });
    if (!navigator.geolocation) return;
    navigator.geolocation.getCurrentPosition((pos) => {
      const { latitude, longitude } = pos.coords;
      // Reverse geocoding ile gerçek şehir adını bul
      fetch(`https://nominatim.openstreetmap.org/reverse?lat=${latitude}&lon=${longitude}&format=json&addressdetails=1`, { headers: { 'Accept-Language': lang === 'tr' ? 'tr,en' : 'en' } })
        .then(r => r.json())
        .then(data => {
          const city = data.address?.city || data.address?.town || data.address?.village || data.address?.county || data.display_name.split(',')[0].trim();
          const country = data.address?.country || '';
          const name = country ? `${city}, ${country}` : city;
          set({ loc: { name, lat: latitude, lon: longitude, alt: 0, tz: Math.round(longitude / 15) } });
        })
        .catch(() => {
          let best = SD.CITIES[0], bd = 1e9;
          SD.CITIES.forEach((c) => { const d = Math.hypot(c.lat - latitude, c.lon - longitude); if (d < bd) { bd = d; best = c; } });
          set({ loc: { ...best, lat: latitude, lon: longitude, name: best.name } });
        });
    }, () => {});
  }, [state.geo]);

  const go = (v) => { setAnim(true); setTimeout(() => { setView(v); setAnim(false); }, 260); };
  const nav = (p) => {
    setAnim(true);
    setTimeout(() => {
      if (p === 'calc') { setPage('calc'); setView('input'); }
      else setPage(p);
      window.scrollTo(0, 0);
      setAnim(false);
    }, 220);
  };

  let body;
  if (page === 'calc') {
    body = view === 'input'
      ? <InputScreen state={state} set={set} onCalc={() => go('result')} t={t} lang={lang} setLang={setLang} nav={nav} />
      : <ResultScreen state={state} onBack={() => go('input')} onRecalc={() => go('input')} t={t} lang={lang} setLang={setLang} nav={nav} />;
  } else if (page === 'about') {
    body = <AboutPage t={t} lang={lang} setLang={setLang} nav={nav} />;
  } else if (page === 'science') {
    body = <SciencePage t={t} lang={lang} setLang={setLang} nav={nav} />;
  } else {
    body = <FaqPage t={t} lang={lang} setLang={setLang} nav={nav} />;
  }

  return <div className={'app' + (anim ? ' fading' : '')}>{body}</div>;
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
