// ── Kalender Widget mit iCal-Unterstützung ────────────────────────────────────
import { useState, useEffect, useMemo } from 'react';
import { api, S } from './lib.js';

// iCal-Parser – unterstützt gefaltete Zeilen, TZID, VALUE=DATE
function parseIcal(raw) {
  // 1. Gefaltete Zeilen (RFC 5545) zusammenführen
  const text = raw.replace(/\r\n[ \t]/g, '').replace(/\r/g, '');

  // 2. Alle Properties als Map extrahieren
  function getProps(block) {
    const props = {};
    for (const line of block.split('\n')) {
      const col = line.indexOf(':');
      if (col < 0) continue;
      const namepart = line.slice(0, col).toUpperCase();
      const val = line.slice(col + 1).trim();
      // Basisname ohne Parameter
      const name = namepart.split(';')[0];
      // TZID-Parameter extrahieren
      const tzidM = namepart.match(/TZID=([^;:]+)/);
      props[name] = { val, raw: namepart, tzid: tzidM?.[1] || null };
    }
    return props;
  }

  // 3. Datum parsen – Ortszeit wenn TZID gesetzt, UTC wenn Z-Suffix
  function parseDate(prop, isEnd) {
    if (!prop) return null;
    const s = prop.val;
    if (!s) return null;
    const allDay = s.length === 8 || prop.raw.includes('VALUE=DATE');
    if (allDay) {
      // DTEND bei all-day ist exklusiv → einen Tag abziehen
      const d = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
      if (isEnd) d.setDate(d.getDate() - 1);
      return { date: d, allDay: true };
    }
    const utc = s.endsWith('Z');
    const y=+s.slice(0,4), mo=+s.slice(4,6)-1, d=+s.slice(6,8);
    const h=+s.slice(9,11)||0, mi=+s.slice(11,13)||0, sec=+s.slice(13,15)||0;
    const date = utc
      ? new Date(Date.UTC(y,mo,d,h,mi,sec))
      : new Date(y,mo,d,h,mi,sec); // Ortszeit des Browsers (beste Annäherung)
    return { date, allDay: false };
  }

  const events = [];
  const blocks = text.split('BEGIN:VEVENT');
  for (let i = 1; i < blocks.length; i++) {
    const end = blocks[i].indexOf('END:VEVENT');
    const block = end >= 0 ? blocks[i].slice(0, end) : blocks[i];
    const p = getProps(block);

    const startObj = parseDate(p['DTSTART']);
    const endObj   = parseDate(p['DTEND'], true) || startObj;
    if (!startObj || isNaN(startObj.date)) continue;

    events.push({
      summary:  (p['SUMMARY']?.val  || '(kein Titel)').replace(/\\n/g,'\n').replace(/\\,/g,','),
      location: (p['LOCATION']?.val || '').replace(/\\n/g,'\n').replace(/\\,/g,','),
      dtstart:  startObj.date,
      dtend:    endObj.date,
      allDay:   startObj.allDay,
    });
  }
  return events;
}

function sameDay(a, b) {
  return a.getFullYear()===b.getFullYear() && a.getMonth()===b.getMonth() && a.getDate()===b.getDate();
}

function inRange(event, day) {
  const d = new Date(day); d.setHours(0,0,0,0);
  const s = new Date(event.dtstart); s.setHours(0,0,0,0);
  const e = new Date(event.dtend);   e.setHours(0,0,0,0);
  return d >= s && d <= e;
}

const WEEKDAYS = ['Mo','Di','Mi','Do','Fr','Sa','So'];
const MONTHS   = ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'];

export default function CalendarWidget() {
  const [isOpen, setIsOpen] = useState(false);
  const [today]  = useState(new Date());
  const [cur,    setCur]    = useState({ y: today.getFullYear(), m: today.getMonth() });
  const [events, setEvents] = useState([]);
  // Feeds immer frisch aus localStorage lesen
  const getFeeds = () => { try { return JSON.parse(localStorage.getItem('dd_cal_feeds') || '[]'); } catch { return []; } };
  const [feedCount, setFeedCount] = useState(0); // trigger re-render
  const [loading, setLoading] = useState(false);
  const [selected, setSelected] = useState(null); // date object

  const [errors, setErrors] = useState([]);

  // Load all feeds
  const loadFeeds = async (feedList) => {
    if (!feedList.length) { setEvents([]); return; }
    setLoading(true);
    setErrors([]);
    const all = [];
    const errs = [];
    for (const f of feedList) {
      try {
        const res = await fetch(`/api/calendar/fetch?url=${encodeURIComponent(f.url)}`, {
          headers: { Authorization: `Bearer ${localStorage.getItem('sk_token')}` }
        });
        if (res.ok) {
          const text = await res.text();
          const evs  = parseIcal(text).map(e => ({ ...e, color: f.color, feedName: f.name }));
          all.push(...evs);
        } else {
          const d = await res.json().catch(()=>({error:'Unbekannter Fehler'}));
          errs.push(`${f.name}: ${d.error}`);
        }
      } catch(e) { errs.push(`${f.name}: ${e.message}`); }
    }
    setEvents(all);
    setErrors(errs);
    setLoading(false);
  };

  const refresh = () => { const f = getFeeds(); if (f.length > 0) loadFeeds(f); setFeedCount(f.length); };
  useEffect(() => { if (isOpen) refresh(); }, [isOpen]);

  // Calendar grid
  const days = useMemo(() => {
    const first = new Date(cur.y, cur.m, 1);
    const dow   = (first.getDay() + 6) % 7; // 0=Mo
    const total = new Date(cur.y, cur.m+1, 0).getDate();
    const grid  = [];
    for (let i = 0; i < dow; i++) grid.push(null);
    for (let d = 1; d <= total; d++) grid.push(new Date(cur.y, cur.m, d));
    return grid;
  }, [cur]);

  const eventsOnDay = (day) => day ? events.filter(e => inRange(e, day)) : [];
  const selectedEvents = selected ? events.filter(e => inRange(e, selected)) : [];

  const prevMonth = () => setCur(p => p.m === 0 ? { y:p.y-1, m:11 } : { y:p.y, m:p.m-1 });
  const nextMonth = () => setCur(p => p.m === 11 ? { y:p.y+1, m:0  } : { y:p.y, m:p.m+1 });

  return (
    <div style={{ ...S.card, marginBottom:10 }}>
      {/* Header */}
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center' }}>
        <button onClick={()=>setIsOpen(v=>!v)} style={{ flex:1, background:'transparent', border:'none',
          display:'flex', justifyContent:'space-between', alignItems:'center', cursor:'pointer', padding:0 }}>
          <div style={S.head}>KALENDER</div>
          <span style={{ color:'rgba(255,255,255,0.4)', fontSize:11, display:'inline-block',
            transform:isOpen?'rotate(90deg)':'rotate(0)', transition:'transform 0.2s' }}>▶</span>
        </button>
        {isOpen && getFeeds().length > 0 && (
          <button onClick={refresh} disabled={loading}
            style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.4)',
              cursor:'pointer', fontSize:13, padding:'0 0 0 8px', marginLeft:8 }}
            title="Neu laden">
            {loading ? '⏳' : '↻'}
          </button>
        )}
      </div>

      {isOpen && (
        <div style={{ marginTop:12 }}>
          {/* Fehler */}
          {errors.length > 0 && (
            <div style={{ marginBottom:10 }}>
              {errors.map((e,i) => (
                <div key={i} style={{ color:'#ff6b9d', fontFamily:'monospace', fontSize:10,
                  background:'rgba(255,107,157,0.08)', borderRadius:6, padding:'4px 8px', marginBottom:3 }}>
                  ✕ {e}
                </div>
              ))}
            </div>
          )}

          {/* Monat Nav */}
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10 }}>
            <button onClick={prevMonth} style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.5)',
              cursor:'pointer', fontSize:18, padding:'0 6px' }}>‹</button>
            <span style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:13, fontWeight:700 }}>
              {MONTHS[cur.m]} {cur.y}
            </span>
            <button onClick={nextMonth} style={{ background:'transparent', border:'none', color:'rgba(255,255,255,0.5)',
              cursor:'pointer', fontSize:18, padding:'0 6px' }}>›</button>
          </div>

          {/* Wochentage */}
          <div style={{ display:'grid', gridTemplateColumns:'repeat(7,1fr)', gap:2, marginBottom:4 }}>
            {WEEKDAYS.map(d => (
              <div key={d} style={{ textAlign:'center', color:'rgba(255,255,255,0.4)', fontFamily:'monospace', fontSize:9 }}>{d}</div>
            ))}
          </div>

          {/* Tage */}
          <div style={{ display:'grid', gridTemplateColumns:'repeat(7,1fr)', gap:2 }}>
            {days.map((day, i) => {
              const evs    = eventsOnDay(day);
              const isToday = day && sameDay(day, today);
              const isSel  = day && selected && sameDay(day, selected);
              return (
                <button key={i} onClick={()=>day&&setSelected(isSel?null:day)} style={{
                  aspectRatio:'1', borderRadius:6, border:'none', cursor:day?'pointer':'default',
                  background: isSel ? 'rgba(78,205,196,0.25)' : isToday ? 'rgba(78,205,196,0.1)' : 'transparent',
                  outline: isToday ? '1px solid rgba(78,205,196,0.4)' : 'none',
                  position:'relative', padding:0, display:'flex', flexDirection:'column',
                  alignItems:'center', justifyContent:'center',
                }}>
                  {day && <>
                    <span style={{ color: isSel?'#4ecdc4':isToday?'#4ecdc4':'rgba(255,255,255,0.75)',
                      fontFamily:'monospace', fontSize:11, fontWeight:isToday?700:400 }}>
                      {day.getDate()}
                    </span>
                    {evs.length > 0 && (
                      <div style={{ display:'flex', gap:1, flexWrap:'wrap', justifyContent:'center', marginTop:1 }}>
                        {evs.slice(0,3).map((e,j) => (
                          <span key={j} style={{ width:4, height:4, borderRadius:'50%',
                            background: e.color || '#4ecdc4', display:'inline-block' }}/>
                        ))}
                      </div>
                    )}
                  </>}
                </button>
              );
            })}
          </div>

          {/* Ausgewählter Tag Events */}
          {selected && (
            <div style={{ marginTop:10, borderTop:'1px solid rgba(255,255,255,0.07)', paddingTop:10 }}>
              <div style={{ color:'rgba(255,255,255,0.55)', fontFamily:'monospace', fontSize:10, marginBottom:6 }}>
                {selected.toLocaleDateString('de-DE',{weekday:'long',day:'numeric',month:'long'})}
              </div>
              {selectedEvents.length === 0
                ? <div style={{ color:'rgba(255,255,255,0.3)', fontFamily:'monospace', fontSize:11 }}>Keine Termine</div>
                : selectedEvents.map((e,i) => (
                  <div key={i} style={{ display:'flex', gap:8, padding:'6px 0',
                    borderBottom:'1px solid rgba(255,255,255,0.05)' }}>
                    <span style={{ width:3, borderRadius:2, background:e.color||'#4ecdc4', flexShrink:0 }}/>
                    <div>
                      <div style={{ color:'#fff', fontFamily:'monospace', fontSize:12 }}>{e.summary}</div>
                      {e.location && <div style={{ color:'rgba(255,255,255,0.4)', fontFamily:'monospace', fontSize:10 }}>{e.location}</div>}
                      {!e.allDay && <div style={{ color:'rgba(255,255,255,0.4)', fontFamily:'monospace', fontSize:10 }}>
                        {e.dtstart.toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit'})}
                        {' – '}{e.dtend.toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit'})}
                      </div>}
                      <div style={{ color:'rgba(255,255,255,0.25)', fontFamily:'monospace', fontSize:9 }}>{e.feedName}</div>
                    </div>
                  </div>
                ))
              }
            </div>
          )}

          {getFeeds().length === 0 && (
            <div style={{ marginTop:10, color:'rgba(255,255,255,0.3)', fontFamily:'monospace', fontSize:11, textAlign:'center' }}>
              Noch keine Kalender abonniert. Füge Kalender in den Einstellungen hinzu.
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ── iCal-Einstellungen (für Einstellungen-Seite) ──────────────────────────────
export function CalendarSettings({ toast }) {
  const [feeds, setFeeds] = useState(() => {
    try { return JSON.parse(localStorage.getItem('dd_cal_feeds') || '[]'); } catch { return []; }
  });
  const [form, setForm] = useState({ name:'', url:'', color:'#4ecdc4' });
  const [testing, setTesting] = useState(false);

  const save = (newFeeds) => {
    setFeeds(newFeeds);
    localStorage.setItem('dd_cal_feeds', JSON.stringify(newFeeds));
  };

  const add = async () => {
    if (!form.name.trim() || !form.url.trim()) { toast('Name und URL erforderlich', 'error'); return; }
    setTesting(true);
    try {
      const res = await fetch(`/api/calendar/fetch?url=${encodeURIComponent(form.url)}`, {
        headers: { Authorization: `Bearer ${localStorage.getItem('sk_token')}` }
      });
      if (!res.ok) { const d=await res.json(); toast(d.error||'Feed-Fehler','error'); return; }
      save([...feeds, { ...form, id: Date.now() }]);
      setForm({ name:'', url:'', color:'#4ecdc4' });
      toast('Kalender hinzugefügt ✓');
    } catch(e) { toast(e.message,'error'); } finally { setTesting(false); }
  };

  const remove = (id) => save(feeds.filter(f => f.id !== id));

  const COLORS = ['#4ecdc4','#ff6b9d','#ffe66d','#6bcb77','#a78bfa','#60a5fa','#fb923c'];

  return (
    <div>
      <div style={{ marginBottom:12 }}>
        <label style={{ ...S.head, display:'block', marginBottom:4 }}>NAME</label>
        <input value={form.name} onChange={e=>setForm(f=>({...f,name:e.target.value}))}
          placeholder="z.B. Google Kalender" style={{ ...S.inp, fontSize:15, marginBottom:8 }}/>
        <label style={{ ...S.head, display:'block', marginBottom:4 }}>ICAL URL</label>
        <input value={form.url} onChange={e=>setForm(f=>({...f,url:e.target.value}))}
          placeholder="https://calendar.google.com/calendar/ical/…"
          style={{ ...S.inp, fontSize:13, marginBottom:8 }}
          autoCapitalize="none" autoCorrect="off"/>
        <label style={{ ...S.head, display:'block', marginBottom:6 }}>FARBE</label>
        <div style={{ display:'flex', gap:6, marginBottom:12 }}>
          {COLORS.map(col => (
            <button key={col} onClick={()=>setForm(f=>({...f,color:col}))} style={{
              width:28, height:28, borderRadius:'50%', background:col, border:'none', cursor:'pointer',
              outline: form.color===col ? '3px solid #fff' : '2px solid transparent',
              outlineOffset:2,
            }}/>
          ))}
        </div>
        <button onClick={add} disabled={testing} style={{ ...S.btn('#4ecdc4'), width:'100%', textAlign:'center', padding:'10px 0' }}>
          {testing ? '⏳ Teste Feed…' : '+ Kalender hinzufügen'}
        </button>
      </div>

      {feeds.length > 0 && (
        <div>
          <div style={{ ...S.head, marginBottom:6 }}>ABONNIERTE KALENDER</div>
          {feeds.map(f => (
            <div key={f.id} style={{ display:'flex', alignItems:'center', gap:10, padding:'8px 0',
              borderBottom:'1px solid rgba(255,255,255,0.05)' }}>
              <span style={{ width:12, height:12, borderRadius:'50%', background:f.color, flexShrink:0 }}/>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ color:'#fff', fontFamily:'monospace', fontSize:12 }}>{f.name}</div>
                <div style={{ color:'rgba(255,255,255,0.4)', fontFamily:'monospace', fontSize:9,
                  overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{f.url}</div>
              </div>
              <button onClick={()=>remove(f.id)} style={{ background:'transparent', border:'none',
                color:'rgba(255,107,157,0.7)', cursor:'pointer', fontSize:16, padding:'0 4px' }}>✕</button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
