/* global React */
// Widget components for SMM dashboard

const { useState, useMemo, useRef, useEffect } = React;

const fmt = (n) => {
  if (typeof n !== 'number') return n;
  if (n >= 1_000_000) return (n / 1_000_000).toFixed(n >= 10_000_000 ? 1 : 2).replace(/\.0+$/, '') + 'M';
  if (n >= 10_000)    return (n / 1000).toFixed(0) + 'K';
  if (n >= 1000)      return (n / 1000).toFixed(1) + 'K';
  return n.toLocaleString('ru-RU');
};
const pct = (cur, prev) => {
  if (!prev) return 0;
  return ((cur - prev) / prev) * 100;
};
const signed = (v) => (v >= 0 ? '+' : '') + v.toFixed(1) + '%';

const KPI_META = {
  'kpi-followers':  { key: 'followers',  color: 'purple', icon: 'fa-users' },
  'kpi-reach':      { key: 'reach',      color: 'blue',   icon: 'fa-bullseye' },
  'kpi-views':      { key: 'views',      color: 'peach',  icon: 'fa-eye' },
  'kpi-engagement': { key: 'engagement', color: 'green',  icon: 'fa-bolt' },
  'kpi-likes':      { key: 'likes',      color: 'yellow', icon: 'fa-heart' },
  'kpi-comments':   { key: 'comments',   color: 'blue',   icon: 'fa-comment' },
};

// ============================================================
// Sparkline (mini line)
// ============================================================
function Spark({ data, color = '#FFD700' }) {
  if (!data || !data.length) return null;
  const w = 200, h = 36;
  const min = Math.min(...data), max = Math.max(...data);
  const r = max - min || 1;
  const pts = data.map((v, i) => [(i / (data.length - 1)) * w, h - ((v - min) / r) * (h - 4) - 2]);
  const path = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const area = path + ` L${w},${h} L0,${h} Z`;
  const id = useMemo(() => 'g' + Math.random().toString(36).slice(2, 8), []);
  return (
    <svg className="kpi-spark" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width: '100%' }}>
      <defs>
        <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.25" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={area} fill={`url(#${id})`} />
      <path d={path} fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// ============================================================
// KPI tile
// ============================================================
function KPIWidget({ id, platform, data, series, compareMode }) {
  const meta = KPI_META[id] || KPI_META['kpi-followers'];
  const k = data.KPI[platform][meta.key];
  if (!k) return null;
  const change = pct(k.v, k.prev);
  const isPos = change >= 0;
  const sparkData = (series[platform] && series[platform].views) || [];
  const sparkColor = platform === 'vk' ? '#0077FF' : platform === 'youtube' ? '#FF0033' : platform === 'instagram' ? '#E1306C' : '#FFD700';
  return (
    <div className="kpi" style={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
      <div className="kpi-head">
        <div className={`kpi-icon ${meta.color}`}>
          <i className={`fas ${meta.icon}`}></i>
        </div>
        <div className={`kpi-trend ${isPos ? 'pos' : 'neg'}`}>
          <i className={`fas fa-arrow-${isPos ? 'up' : 'down'}`} style={{ fontSize: 9 }}></i>
          {signed(change).replace('+', '').replace('-', '')}
        </div>
      </div>
      <div className="kpi-value">
        {k.unit ? `${k.v}${k.unit}` : fmt(k.v)}
      </div>
      <div className="kpi-label">{k.label}</div>
      <div className="kpi-foot">
        <span>vs. предыдущий период</span>
      </div>
      <Spark data={sparkData} color={sparkColor} />
    </div>
  );
}

// ============================================================
// Area chart — views trend
// ============================================================
function AreaChart({ platform, series, compareMode }) {
  const [hover, setHover] = useState(null);
  const wrapRef = useRef(null);
  const [size, setSize] = useState({ w: 720, h: 280 });

  useEffect(() => {
    const ro = new ResizeObserver(es => {
      for (const e of es) {
        setSize({ w: e.contentRect.width, h: Math.max(220, e.contentRect.height) });
      }
    });
    if (wrapRef.current) ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const data = useMemo(() => {
    if (platform === 'all') {
      return {
        sets: [
          { id: 'vk',        label: 'ВКонтакте', color: '#0077FF', d: series.vk.views },
          { id: 'youtube',   label: 'YouTube',   color: '#FF0033', d: series.youtube.views },
          { id: 'instagram', label: 'Instagram', color: '#E1306C', d: series.instagram.views },
        ],
      };
    }
    return {
      sets: [
        { id: platform, label: window.SMM_DATA.PLATFORMS[platform].name, color: window.SMM_DATA.PLATFORMS[platform].color, d: series[platform].views },
        ...(compareMode ? [{ id: 'prev', label: 'Прошлый период', color: '#B7B7BD', dashed: true, d: series[platform].views.map(v => Math.round(v * (0.84 + Math.random() * 0.08))) }] : []),
      ],
    };
  }, [platform, compareMode, series]);

  const padding = { t: 16, r: 16, b: 28, l: 44 };
  const W = size.w, H = size.h;
  const innerW = W - padding.l - padding.r, innerH = H - padding.t - padding.b;
  const all = data.sets.flatMap(s => s.d);
  const max = Math.max(...all);
  const min = 0;
  const len = data.sets[0].d.length;
  const xAt = (i) => padding.l + (i / (len - 1)) * innerW;
  const yAt = (v) => padding.t + innerH - ((v - min) / (max - min)) * innerH;

  const ticksY = useMemo(() => {
    const step = Math.pow(10, Math.floor(Math.log10(max / 4)));
    const niceStep = step * (max / 4 / step < 2 ? 2 : max / 4 / step < 5 ? 5 : 10);
    const arr = [];
    for (let v = 0; v <= max; v += niceStep) arr.push(v);
    if (arr[arr.length - 1] < max) arr.push(max);
    return arr;
  }, [max]);

  // x labels — show 5 dates
  const days = useMemo(() => {
    const today = new Date();
    return Array.from({ length: len }, (_, i) => {
      const d = new Date(today);
      d.setDate(today.getDate() - (len - 1 - i));
      return d;
    });
  }, [len]);

  return (
    <div ref={wrapRef} className="chart-wrap" style={{ position: 'relative', height: 300 }}>
      <svg width={W} height={H} style={{ display: 'block' }} onMouseLeave={() => setHover(null)}>
        <defs>
          {data.sets.map(s => (
            <linearGradient key={s.id} id={`a_${s.id}`} x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor={s.color} stopOpacity={s.dashed ? 0.05 : 0.20} />
              <stop offset="100%" stopColor={s.color} stopOpacity="0" />
            </linearGradient>
          ))}
        </defs>
        {/* y grid */}
        {ticksY.map((t, i) => (
          <g key={i}>
            <line x1={padding.l} x2={W - padding.r} y1={yAt(t)} y2={yAt(t)} stroke="var(--line)" strokeDasharray={i ? '3 4' : undefined} />
            <text x={padding.l - 8} y={yAt(t) + 4} textAnchor="end" fontSize="10" fill="var(--text-3)">{fmt(t)}</text>
          </g>
        ))}
        {/* x labels */}
        {[0, Math.floor(len/4), Math.floor(len/2), Math.floor(len*3/4), len-1].map(i => (
          <text key={i} x={xAt(i)} y={H - 8} fontSize="10" fill="var(--text-3)" textAnchor="middle">
            {days[i].getDate()} {['янв','фев','мар','апр','мая','июн','июл','авг','сен','окт','ноя','дек'][days[i].getMonth()]}
          </text>
        ))}
        {/* areas */}
        {data.sets.map(s => {
          const pts = s.d.map((v, i) => [xAt(i), yAt(v)]);
          const path = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
          const area = path + ` L${xAt(len - 1)},${yAt(0)} L${xAt(0)},${yAt(0)} Z`;
          return (
            <g key={s.id}>
              <path d={area} fill={`url(#a_${s.id})`} />
              <path d={path} fill="none" stroke={s.color} strokeWidth={s.dashed ? 1.5 : 2.4} strokeLinecap="round" strokeLinejoin="round" strokeDasharray={s.dashed ? '4 4' : undefined} />
            </g>
          );
        })}
        {/* hover hit area */}
        <rect x={padding.l} y={padding.t} width={innerW} height={innerH} fill="transparent"
          onMouseMove={(e) => {
            const rect = e.currentTarget.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const i = Math.round((x / innerW) * (len - 1));
            setHover(Math.max(0, Math.min(len - 1, i)));
          }}
        />
        {hover != null && (
          <g>
            <line x1={xAt(hover)} x2={xAt(hover)} y1={padding.t} y2={H - padding.b} stroke="var(--text-3)" strokeWidth="1" strokeDasharray="3 3" />
            {data.sets.map(s => (
              <circle key={s.id} cx={xAt(hover)} cy={yAt(s.d[hover])} r="4" fill="white" stroke={s.color} strokeWidth="2" />
            ))}
          </g>
        )}
      </svg>
      {hover != null && (
        <div style={{
          position: 'absolute',
          left: Math.min(xAt(hover) - 70, W - 160),
          top: padding.t,
          background: '#0E0E10',
          color: 'white',
          padding: '10px 12px',
          borderRadius: 10,
          fontSize: 12,
          boxShadow: '0 8px 24px rgba(0,0,0,0.2)',
          pointerEvents: 'none',
          minWidth: 140,
          zIndex: 5,
        }}>
          <div style={{ fontSize: 10, color: 'rgba(255,255,255,0.5)', marginBottom: 4 }}>
            {days[hover].toLocaleDateString('ru-RU', { day: 'numeric', month: 'long' })}
          </div>
          {data.sets.map(s => (
            <div key={s.id} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, padding: '2px 0' }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 8, height: 8, borderRadius: 2, background: s.color }} />
                <span>{s.label}</span>
              </span>
              <strong>{fmt(s.d[hover])}</strong>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ============================================================
// Bar chart — likes & comments
// ============================================================
function BarChart({ platform, series, compareMode }) {
  const [hover, setHover] = useState(null);
  const wrapRef = useRef(null);
  const [size, setSize] = useState({ w: 720, h: 280 });
  useEffect(() => {
    const ro = new ResizeObserver(es => { for (const e of es) setSize({ w: e.contentRect.width, h: Math.max(240, e.contentRect.height) }); });
    if (wrapRef.current) ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);
  const lastN = 14;
  const sets = useMemo(() => {
    const slice = (a) => a.slice(-lastN);
    if (platform === 'all') {
      return [
        { id: 'likes',    label: 'Лайки',        color: '#FFD700', d: slice(series.all.likes) },
        { id: 'comments', label: 'Комментарии',  color: '#0077FF', d: slice(series.all.comments) },
      ];
    }
    return [
      { id: 'likes',    label: 'Лайки',        color: window.SMM_DATA.PLATFORMS[platform].color, d: slice(series[platform].likes) },
      { id: 'comments', label: 'Комментарии',  color: '#0E0E10', d: slice(series[platform].comments) },
    ];
  }, [platform, series]);

  const padding = { t: 16, r: 16, b: 28, l: 44 };
  const W = size.w, H = size.h;
  const innerW = W - padding.l - padding.r, innerH = H - padding.t - padding.b;
  const max = Math.max(...sets.flatMap(s => s.d));
  const groupW = innerW / lastN;
  const barW = (groupW - 6) / sets.length;
  const yAt = (v) => padding.t + innerH - (v / max) * innerH;
  const ticksY = [0, 0.25, 0.5, 0.75, 1].map(p => p * max);

  const today = new Date();
  const days = Array.from({ length: lastN }, (_, i) => {
    const d = new Date(today);
    d.setDate(today.getDate() - (lastN - 1 - i));
    return d;
  });

  return (
    <div ref={wrapRef} className="chart-wrap" style={{ position: 'relative', height: 300 }}>
      <svg width={W} height={H} style={{ display: 'block' }} onMouseLeave={() => setHover(null)}>
        {ticksY.map((t, i) => (
          <g key={i}>
            <line x1={padding.l} x2={W - padding.r} y1={yAt(t)} y2={yAt(t)} stroke="var(--line)" strokeDasharray={i ? '3 4' : undefined} />
            <text x={padding.l - 8} y={yAt(t) + 4} textAnchor="end" fontSize="10" fill="var(--text-3)">{fmt(t)}</text>
          </g>
        ))}
        {sets[0].d.map((_, i) => {
          const xBase = padding.l + i * groupW + 3;
          return (
            <g key={i} onMouseEnter={() => setHover(i)}>
              <rect x={padding.l + i * groupW} y={padding.t} width={groupW} height={innerH} fill="transparent" />
              {sets.map((s, si) => {
                const v = s.d[i];
                const h = (v / max) * innerH;
                return (
                  <rect key={s.id}
                    x={xBase + si * barW}
                    y={padding.t + innerH - h}
                    width={Math.max(2, barW - 4)}
                    height={h}
                    rx={3}
                    fill={s.color}
                    opacity={hover != null && hover !== i ? 0.35 : 1}
                  />
                );
              })}
              {(i % 3 === 0 || i === sets[0].d.length - 1) && (
                <text x={padding.l + i * groupW + groupW / 2} y={H - 8} fontSize="10" fill="var(--text-3)" textAnchor="middle">
                  {days[i].getDate()}/{days[i].getMonth() + 1}
                </text>
              )}
            </g>
          );
        })}
      </svg>
      {hover != null && (
        <div style={{
          position: 'absolute',
          left: Math.min(padding.l + hover * groupW + groupW / 2 + 8, W - 180),
          top: padding.t + 8,
          background: '#0E0E10',
          color: 'white',
          padding: '10px 12px',
          borderRadius: 10,
          fontSize: 12,
          minWidth: 150,
          pointerEvents: 'none',
        }}>
          <div style={{ fontSize: 10, color: 'rgba(255,255,255,0.5)', marginBottom: 6 }}>
            {days[hover].toLocaleDateString('ru-RU', { day: 'numeric', month: 'long' })}
          </div>
          {sets.map(s => (
            <div key={s.id} style={{ display: 'flex', justifyContent: 'space-between', gap: 12, padding: '2px 0' }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 8, height: 8, borderRadius: 2, background: s.color }} />
                <span>{s.label}</span>
              </span>
              <strong>{fmt(s.d[hover])}</strong>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ============================================================
// Gender donut
// ============================================================
function GenderDonut({ platform, data }) {
  const g = data.GENDER[platform];
  const cx = 70, cy = 70, R = 56, r = 38;
  const total = g.f + g.m;
  const fAngle = (g.f / total) * Math.PI * 2;
  const path = (start, end) => {
    const large = end - start > Math.PI ? 1 : 0;
    const sx = cx + R * Math.sin(start), sy = cy - R * Math.cos(start);
    const ex = cx + R * Math.sin(end),   ey = cy - R * Math.cos(end);
    const isx = cx + r * Math.sin(end),  isy = cy - r * Math.cos(end);
    const iex = cx + r * Math.sin(start),iey = cy - r * Math.cos(start);
    return `M${sx},${sy} A${R},${R} 0 ${large} 1 ${ex},${ey} L${isx},${isy} A${r},${r} 0 ${large} 0 ${iex},${iey} Z`;
  };
  return (
    <div className="gender-card">
      <div className="gender-svg">
        <svg viewBox="0 0 140 140" width="140" height="140">
          <path d={path(0, fAngle)} fill="#E1306C" />
          <path d={path(fAngle, Math.PI * 2)} fill="#0077FF" />
        </svg>
        <div className="gender-center">
          <div>
            <div className="gc-num">{fmt(data.KPI[platform].followers.v)}</div>
            <div className="gc-sub">подписчиков</div>
          </div>
        </div>
      </div>
      <div className="gender-legend">
        <div className="gl-row">
          <span className="gl-pill"><span className="ldot" style={{ background: '#E1306C' }}></span>Женщины</span>
          <span className="gl-val">{g.f}%</span>
        </div>
        <div className="gl-row">
          <span className="gl-pill"><span className="ldot" style={{ background: '#0077FF' }}></span>Мужчины</span>
          <span className="gl-val">{g.m}%</span>
        </div>
        <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 8, paddingTop: 10, borderTop: '1px solid var(--line)' }}>
          Преобладание: {g.f > g.m ? 'женская' : 'мужская'} аудитория
        </div>
      </div>
    </div>
  );
}

// ============================================================
// Age widget — horizontal bars
// ============================================================
function AgeWidget({ platform, data }) {
  const ages = data.AGE[platform];
  const max = Math.max(...ages.map(a => a.v));
  const cls = platform === 'vk' ? 'vk' : platform === 'youtube' ? 'yt' : platform === 'instagram' ? 'ig' : '';
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
      {ages.map(a => (
        <div className="demo-row" key={a.b}>
          <div className="demo-label">{a.b}</div>
          <div className={`demo-bar ${cls}`}>
            <span style={{ width: `${(a.v / max) * 100}%` }}></span>
          </div>
          <div className="demo-val">{a.v}%</div>
        </div>
      ))}
    </div>
  );
}

// ============================================================
// Geography
// ============================================================
function GeoWidget({ platform, data }) {
  const geo = (data.GEO && data.GEO[platform]) || [];
  if (geo.length === 0) {
    return <div className="muted-empty">Нет данных по географии</div>;
  }
  const max = Math.max(...geo.map(g => g.v)) || 1;
  return (
    <div className="geo-list">
      {geo.map(g => (
        <div className="geo-row" key={g.city}>
          <div className="geo-flag">{g.flag}</div>
          <div>
            <div className="geo-city">{g.city}</div>
            <div className="geo-country">{g.country}</div>
            <div className="geo-bar"><span style={{ width: `${(g.v / max) * 100}%` }} /></div>
          </div>
          <div className="geo-val">{g.v}%</div>
        </div>
      ))}
    </div>
  );
}

// ============================================================
// Sources widget
// ============================================================
function SourcesWidget({ platform, data }) {
  const s = (data.SOURCES && data.SOURCES[platform]) || [];
  if (s.length === 0) {
    return <div className="muted-empty">Нет данных об источниках</div>;
  }
  const total = s.reduce((a, b) => a + b.v, 0);
  return (
    <div>
      <div className="sources-stack">
        {s.map(it => (
          <span key={it.id} style={{ flex: it.v, background: it.color }} title={`${it.label} ${it.v}%`}></span>
        ))}
      </div>
      <div className="sources-legend">
        {s.map(it => {
          const d = it.v - it.prev;
          return (
            <div className="sources-row" key={it.id}>
              <span className="label"><span className="ldot" style={{ width: 10, height: 10, borderRadius: 3, background: it.color, display: 'inline-block' }}></span>{it.label}</span>
              <span className="pct">{it.v}%</span>
              <span className={`delta ${d >= 0 ? 'pos' : 'neg'}`}>{d >= 0 ? '+' : ''}{d}п.п.</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ============================================================
// Top posts
// ============================================================
function PostsWidget({ platform, data }) {
  const posts = (data.POSTS && (data.POSTS[platform] || data.POSTS.all)) || [];
  if (posts.length === 0) {
    return <div className="muted-empty">Нет постов за период</div>;
  }
  const platformIcons = {
    vk: { icon: 'fab fa-vk', bg: '#0077FF' },
    youtube: { icon: 'fab fa-youtube', bg: '#FF0033' },
    instagram: { icon: 'fab fa-instagram', bg: '#E1306C' },
  };
  return (
    <div className="posts-list">
      {posts.map(p => {
        const pi = platformIcons[p.platform] || { icon: 'fas fa-image', bg: '#888' };
        return (
          <div className="post-row" key={p.id}>
            <div className="post-thumb" style={{ backgroundImage: `url(${p.img})` }}>
              <div className="pt-badge" style={{ background: pi.bg }}>
                <i className={pi.icon} style={{ fontSize: 7 }}></i>
              </div>
            </div>
            <div className="post-meta">
              <div className="post-title">{p.title}</div>
              <div className="post-sub">
                <span><i className="fas fa-heart" style={{ fontSize: 9 }}></i>{p.likes}</span>
                <span><i className="fas fa-comment" style={{ fontSize: 9 }}></i>{p.comments}</span>
                <span>{p.sub}</span>
              </div>
            </div>
            <div className="post-engagement">
              {p.views}<small>просмотров</small>
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ============================================================
// Comparison widget
// ============================================================
function CompareWidget({ data }) {
  const platforms = ['vk', 'youtube', 'instagram'];
  return (
    <div className="compare-grid">
      {platforms.map(p => {
        const pl = data.PLATFORMS[p];
        const k = data.KPI[p];
        const rows = [
          { lab: 'Подписчики',  v: fmt(k.followers.v), d: pct(k.followers.v, k.followers.prev) },
          { lab: 'Охват',       v: fmt(k.reach.v),     d: pct(k.reach.v, k.reach.prev) },
          { lab: 'Просмотры',   v: fmt(k.views.v),     d: pct(k.views.v, k.views.prev) },
          { lab: 'Лайки',       v: fmt(k.likes.v),     d: pct(k.likes.v, k.likes.prev) },
          { lab: 'Комментарии', v: fmt(k.comments.v),  d: pct(k.comments.v, k.comments.prev) },
          { lab: 'ER',          v: `${k.engagement.v}%`, d: pct(k.engagement.v, k.engagement.prev) },
        ];
        return (
          <div className="compare-cell" key={p}>
            <div className="compare-cell-head">
              <div className={`platform-icon ${p}`}><i className={pl.icon}></i></div>
              {pl.name}
            </div>
            <div className="compare-cell-rows">
              {rows.map(r => (
                <div className="compare-cell-row" key={r.lab}>
                  <span className="lab">{r.lab}</span>
                  <span>
                    <span className="val">{r.v}</span>
                    <span className={`delta ${r.d >= 0 ? 'pos' : 'neg'}`}>{signed(r.d).replace(/\.0+/, '')}</span>
                  </span>
                </div>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ============================================================
// Stories strip
// ============================================================
function StoriesWidget({ data }) {
  const platformBg = { vk: '#0077FF', youtube: '#FF0033', instagram: '#E1306C' };
  const platformIcon = { vk: 'fab fa-vk', youtube: 'fab fa-youtube', instagram: 'fab fa-instagram' };
  return (
    <div className="stories-strip">
      <div className="story add">
        <div className="add-inner">
          <div className="add-icon"><i className="fas fa-plus"></i></div>
          <span>Создать пост</span>
        </div>
      </div>
      {data.STORIES.map(s => (
        <div className="story" key={s.id} style={{ backgroundImage: `url(${s.img})` }}>
          <div className="story-platform" style={{ background: platformBg[s.platform] }}>
            <i className={platformIcon[s.platform]} style={{ fontSize: 9 }}></i>
          </div>
          <div className="story-name">{s.name}</div>
        </div>
      ))}
    </div>
  );
}

// Export
Object.assign(window, {
  KPIWidget, AreaChart, BarChart, GenderDonut, AgeWidget, GeoWidget,
  SourcesWidget, PostsWidget, CompareWidget, StoriesWidget,
  fmt, pct, signed, KPI_META,
});
