/* Лента событий — Telegram-канал + афиша */

/* ============================================================
   ПОДКЛЮЧЕНИЕ СОБЫТИЙ ИЗ БАЗЫ ТГ-БОТА (Railway / Postgres)
   ------------------------------------------------------------
   Браузер не может читать Postgres напрямую — нужен HTTP-API,
   который отдаёт события в JSON. Когда у dzagli-bot появится
   такой эндпоинт, впишите его адрес сюда — афиша подтянет
   реальные события. Пустая строка = работаем на тестовых данных.

   Бэкенд должен отдавать массив объектов и слать заголовок
   Access-Control-Allow-Origin (CORS). Ожидаемые поля (любое из
   синонимов подойдёт — см. adaptEvent ниже):
     id            — id события
     title|name    — название
     starts_at|date|datetime — дата-время (ISO), из неё берутся
                     число, месяц, день недели и время
     category|format|category_name — рубрика (ЧТЕНИЯ, КИНО, …)
     audience|who  — 'все' | 'взрослые' | 'подростки'
     space|location|place — где (Кинозал, Двор, …)
     price         — число (₾) или строка ('бесплатно', 'свободный взнос')
     seats|capacity — мест
     description|desc — описание
     photos[]|photo|image — фото (url или подпись)
   ============================================================ */
const EVENTS_API = 'https://dzagli-bot-production.up.railway.app/api/events';

const MON_RU = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'];
const DOW_RU = ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'];
const pad2 = (n) => String(n).padStart(2, '0');

/* Приводит строку из БД к виду, который рендерит EventRow */
const AUD_SET = ['все', 'взрослые', 'подростки', 'дети'];
const isVideoUrl = (u) => /\.(mp4|mov|webm|m4v|ogv)(\?|#|$)/i.test(u || '') || /\/(video|videos)\//i.test(u || '');

/* Собирает все медиа события в единый список {type, url}, видео — первым.
   posters — кадры-превью для тяжёлых видео (>20 МБ), показываем как фолбэк. */
function collectMedia(r) {
  const out = [];
  const push = (url, type) => {if (url && typeof url === 'string') out.push({ url, type: type || (isVideoUrl(url) ? 'video' : 'image') });};
  /* явные поля видео */
  push(r.video, 'video');
  (Array.isArray(r.videos) ? r.videos : []).forEach((u) => push(u, 'video'));
  /* обобщённый media[] из {type,url} */
  (Array.isArray(r.media) ? r.media : []).forEach((m) => {
    if (!m) return;
    if (typeof m === 'string') push(m);else
    push(m.url || m.src || m.file, (m.type || '').toLowerCase().includes('video') ? 'video' : undefined);
  });
  /* постеры тяжёлых видео — как картинка-фолбэк */
  (Array.isArray(r.posters) ? r.posters : []).forEach((u) => push(u, 'poster'));
  push(r.poster, 'poster');
  /* фото */
  (Array.isArray(r.photos) ? r.photos : []).forEach((u) => push(u, 'image'));
  push(r.photo || r.image || r.img, 'image');
  /* видео — вперёд, дубли убираем */
  const seen = new Set();
  return out.filter((m) => seen.has(m.url) ? false : (seen.add(m.url), true)).
  sort((a, b) => (a.type === 'video' ? -1 : 0) - (b.type === 'video' ? -1 : 0));
}

function adaptEvent(r, i) {
  const raw = r.starts_at || r.start_at || r.date || r.datetime || r.start_time || r.start || null;
  const d = raw ? new Date(raw) : null;
  const valid = d && !isNaN(d.getTime());
  let price = r.price;
  if (typeof price === 'number') price = price > 0 ? price + ' ₾' : ''; /* 0 = цена в описании, не показываем «бесплатно» */
  const media = collectMedia(r);
  /* категория события из бота: взрослые | подростки | дети | все */
  let cat = (r.category || r.audience || r.who || 'все').toString().toLowerCase().trim();
  if (!AUD_SET.includes(cat)) cat = 'все';
  let seats = r.seats != null ? r.seats : r.capacity;
  if (typeof seats === 'number') seats = seats + ' мест';else
  if (!seats) seats = '';
  return {
    id: r.id != null ? r.id : i,
    _ts: valid ? d.getTime() : 0,
    day: valid ? pad2(d.getDate()) : r.day || '',
    mon: valid ? MON_RU[d.getMonth()] : r.mon || '',
    dow: valid ? DOW_RU[d.getDay()] : r.dow || '',
    time: valid ? pad2(d.getHours()) + ':' + pad2(d.getMinutes()) : r.time || '',
    who: cat,
    space: r.space || r.location || r.place || r.venue || '',
    title: r.title || r.name || 'Событие',
    price: price != null ? price : '',
    seats,
    desc: r.desc || r.description || '',
    media,
    img: (media.find((m) => m.type === 'image' || m.type === 'poster') || {}).url || ''
  };
}

/* Тянет события из API (если задан), иначе — тестовые из window.DATA */
function useEvents() {
  const [events, setEvents] = useState(window.DATA.events);
  const [state, setState] = useState(EVENTS_API ? 'loading' : 'mock');
  useEffect(() => {
    if (!EVENTS_API) return;
    let alive = true;
    fetch(EVENTS_API).
    then((r) => {if (!r.ok) throw new Error('HTTP ' + r.status);return r.json();}).
    then((rows) => {
      if (!alive) return;
      const arr = Array.isArray(rows) ? rows : rows.events || rows.data || [];
      const mapped = arr.map(adaptEvent).sort((a, b) => b._ts - a._ts); /* свежее — сверху */
      if (mapped.length) {setEvents(mapped);setState('db');} else
      setState('empty');
    }).
    catch(() => {if (alive) setState('error');});
    return () => {alive = false;};
  }, []);
  return { events, state };
}

/* === Telegram-канал === */
/* Хэндл канала без @. Поменять тут — поменяется везде на странице. */
const TG_CHANNEL = 'dzagli_tbi';
/* Живые посты из канала: номера сообщений (t.me/<канал>/<номер>).
   Замените на ссылки ваших реальных постов — порядок сверху вниз. */
const TG_POSTS = ['5', '4', '3', '2'];

/* Один встроенный пост через официальный виджет Telegram */
function TgPost({ id }) {
  const ref = useRef(null);
  useEffect(() => {
    const host = ref.current;
    if (!host) return;
    host.innerHTML = '';
    const s = document.createElement('script');
    s.async = true;
    s.src = 'https://telegram.org/js/telegram-widget.js?22';
    s.setAttribute('data-telegram-post', TG_CHANNEL + '/' + id);
    s.setAttribute('data-width', '100%');
    s.setAttribute('data-dark', '0');
    host.appendChild(s);
  }, [id]);
  return <div ref={ref} className="tg-post"></div>;
}

function TelegramFeed() {
  return (
    <>
      <div className="tg-channel">
        <div className="tg-channel__left">
          <span className="mono eyebrow eyebrow--green">прямой эфир · telegram</span>
          <h3 className="wrapb">Лента дома — в нашем Telegram</h3>
          <p className="prettyw">
            Анонсы событий, фотоотчёты, наборы в школу и просто жизнь Собаки — первыми
            и без алгоритмов. Подписывайтесь, чтобы ничего не пропустить.
          </p>
          <div className="tg-channel__handle">
            <span className="tg-channel__dot"></span>
            <span className="mono" style={{ fontSize: 13, letterSpacing: '0.02em' }}>@{TG_CHANNEL}</span>
          </div>
        </div>
        <a className="btn btn--solid" href={'https://t.me/' + TG_CHANNEL} target="_blank" rel="noopener noreferrer">
          Подписаться в Telegram <Arrow className="arr" />
        </a>
      </div>
    </>);

}

/* === Афиша (кураторская) === */
function Feed({ go }) {
  const [aud, setAud] = useState('все');
  const { events: all, state } = useEvents();
  const list = aud === 'все' ? all : all.filter((e) => e.who === aud || e.who === 'все');
  const auds = [['все', 'Всё'], ['взрослые', 'Взрослым'], ['подростки', 'Подросткам'], ['дети', 'Детям']];

  /* делим на предстоящие и прошедшие по дате начала (конец дня события) */
  const now = Date.now();
  const ts = (e) => e._ts || 0;
  const isPast = (e) => ts(e) > 0 && ts(e) + 36e5 * 6 < now; /* +6ч буфера на длительность */
  const upcoming = list.filter((e) => !isPast(e)).sort((a, b) => ts(a) - ts(b)); /* ближайшее — сверху */
  const past = list.filter(isPast).sort((a, b) => ts(b) - ts(a)); /* недавнее — сверху */

  return (
    <div className="wrap section-pad">
      <SectionHead index="01" kicker="лента событий"
      title="Афиша дома"
      intro="Чтения, кино, квартирники, мастерские и языковые классы. Регистрация и билеты — через Luma. Места ограничены: в доме уютно, но тесно." />

      {/* живая лента из Telegram */}
      <TelegramFeed />

      {/* заголовок кураторской афиши */}
      <div className="feed-secthead">
        <span className="tag green">[ афиша ]</span>
        <span className="mono faint" style={{ fontSize: 12 }}>билеты и регистрация</span>
      </div>

      {/* фильтр аудитории */}
      <div className="flex between center" style={{ marginBottom: 30, flexWrap: 'wrap', gap: 16 }}>
        <div className="flex gap-s" style={{ flexWrap: 'wrap' }}>
          {auds.map(([id, l]) =>
          <button key={id} className={'chip' + (aud === id ? ' is-on' : '')} onClick={() => setAud(id)}>{l}</button>
          )}
        </div>
        <span className="mono faint" style={{ fontSize: 12 }}>
          {state === 'loading' ? 'загрузка из базы…' :
          list.length + ' событий · ' + (state === 'db' ? 'из базы бота' : 'тест')}
        </span>
      </div>

      {/* ПРЕДСТОЯЩИЕ */}
      <div className="feed-group__head">
        <span className="feed-group__dot"></span>
        <span className="feed-group__label">Предстоящие</span>
        <span className="mono faint" style={{ fontSize: 12 }}>{upcoming.length}</span>
        <hr className="rule rule--soft" style={{ flex: 1 }} />
      </div>
      {upcoming.length ?
      <div>{upcoming.map((e, i) => <EventRow key={e.id} e={e} i={i} go={go} />)}</div> :
      <p className="mono faint" style={{ fontSize: 13, padding: '14px 4px 8px' }}>Пока нет анонсов в этой категории — заглядывайте позже.</p>}

      {/* ПРОШЕДШИЕ */}
      {past.length > 0 &&
      <div className="feed-past">
          <div className="feed-group__head">
            <span className="feed-group__label feed-group__label--muted">Прошедшие</span>
            <span className="mono faint" style={{ fontSize: 12 }}>{past.length}</span>
            <hr className="rule rule--soft" style={{ flex: 1 }} />
          </div>
          <div>{past.map((e, i) => <EventRow key={e.id} e={e} i={i} go={go} past />)}</div>
        </div>
      }

      {/* подвал-приглашение */}
      <div className="feed-cta">
        <div>
          <div className="mono eyebrow eyebrow--green" style={{ marginBottom: 10 }}>хотите провести своё?</div>
          <h3 style={{ fontSize: 'clamp(26px,3.6vw,40px)', maxWidth: '18ch' }} className="wrapb">Предложите формат — мы дадим сцену, чай и публику.</h3>
        </div>
        <button className="btn btn--green" onClick={() => go('rental')}>Арендовать пространство <Arrow className="arr" /></button>
      </div>
    </div>);

}

function EventMedia({ e }) {
  const [failed, setFailed] = useState(false);
  const media = e.media && e.media.length ? e.media :
  e.img ? [{ type: 'image', url: e.img }] : [];
  const first = media[0];
  const isVideo = first && first.type === 'video';

  /* видео-прокси может вернуть 413 (тяжёлый файл) без чистого error-события —
     проверяем доступность лёгким range-запросом и падаем в фолбэк заранее */
  useEffect(() => {
    if (!isVideo) return;
    let alive = true;
    fetch(first.url, { headers: { Range: 'bytes=0-1' } }).
    then((r) => {
      const ct = r.headers.get('content-type') || '';
      if (!alive) return;
      if (!r.ok && r.status !== 206) setFailed(true);else
      if (!/video\//i.test(ct)) setFailed(true);
    }).
    catch(() => {if (alive) setFailed(true);});
    return () => {alive = false;};
  }, [isVideo, first && first.url]);

  if (!media.length) return <Ph label="фото события" ratio="16/7" />;
  const poster = (media.find((m) => m.type === 'image' || m.type === 'poster') || {}).url;
  if (isVideo) {
    if (failed) {
      /* видео не отдалось (тяжёлое >20 МБ или ошибка прокси) — показываем постер-кадр или заглушку */
      return poster ?
      <img className="ev-row__img" src={poster} alt={e.title} loading="lazy" /> :
      <Ph label="видео недоступно" ratio="16/9" />;
    }
    return (
      <video className="ev-row__img" controls playsInline preload="metadata"
      src={first.url}
      poster={poster || undefined}
      onError={() => setFailed(true)} />);

  }
  return <img className="ev-row__img" src={first.url} alt={e.title} loading="lazy"
  onError={(ev) => {ev.target.style.display = 'none';}} />;
}

function EventRow({ e, i, go, past }) {
  const [open, setOpen] = useState(false);
  const whoLabel = { 'взрослые': '18+', 'подростки': '12–17', 'дети': 'дети', 'все': 'для всех' }[e.who] || e.who;
  return (
    <div className={'ev-row' + (past ? ' ev-row--past' : '')} style={{ borderBottom: '1px solid var(--paper-3)' }}>
      <button className="ev-row__head" onClick={() => setOpen((o) => !o)}>
        <div className="ev-row__date">
          <span className="serif ev-row__day">{e.day}</span>
          <span className="mono ev-row__mon">{e.mon}<br />{e.dow}</span>
        </div>
        <div className="ev-row__main">
          <div className="flex gap-s center" style={{ marginBottom: 7, flexWrap: 'wrap' }}>
            {e.format ? <span className="ev-pill ev-pill--green">{e.format}</span> : null}
            <span className="ev-pill">{whoLabel}</span>
            <span className="mono faint" style={{ fontSize: 12 }}>{e.time} · {e.space}</span>
          </div>
          <div className="serif ev-row__title">{e.title}</div>
        </div>
        <div className="ev-row__price">
          {e.price ? <span className="mono" style={{ fontSize: 13, color: past ? 'var(--ink-faint)' : 'var(--green)' }}>{e.price}</span> : null}
          {e.seats ? <span className="mono faint" style={{ fontSize: 11.5 }}>{e.seats}</span> : null}
          <span className="ev-row__chev mono">{open ? '−' : '+'}</span>
        </div>
      </button>
      {open &&
      <div className="ev-row__body">
          <EventMedia e={e} />
          <div className="ev-row__detail">
            <p className="prettyw ev-row__desc">{e.desc}</p>
            <div className="flex gap-s" style={{ marginTop: 18, flexWrap: 'wrap' }}>
              {past ?
            <button className="btn btn--ghost" disabled style={{ opacity: .55, cursor: 'default' }}>Событие завершено</button> :
            <button className="btn btn--solid">Регистрация · Luma <Arrow className="arr" /></button>}
            </div>
          </div>
        </div>
      }
    </div>);

}
Object.assign(window, { Feed, useEvents });