// Charts: GitHub-style heatmap with soft rounded tiles, sparkline/bar charts, calendar

// Heatmap: 7 rows × N weeks, soft rounded tiles
const Heatmap = ({ days, onCellClick, monthsShown=6 }) => {
  // days: [{date, rating, isDefault, ...}], sorted ascending, aligned to start Monday
  if (!days || !days.length) return null;
  const weeks = [];
  for (let i = 0; i < days.length; i += 7) weeks.push(days.slice(i, i+7));
  const lvl = (d) => `var(--level-${d.rating})`;
  const months = ['Янв','Фев','Мар','Апр','Май','Июн','Июл','Авг','Сен','Окт','Ноя','Дек'];

  // month labels: find the first column index of each new month
  const monthLabels = [];
  let lastMonth = -1;
  weeks.forEach((w, wi) => {
    const firstDate = new Date(w[0].date);
    const m = firstDate.getMonth();
    if (m !== lastMonth) { monthLabels.push({ wi, label: months[m] }); lastMonth = m; }
  });

  return (
    <div style={{ overflowX:'auto', padding:'8px 2px 2px' }}>
      <div style={{ display:'inline-flex', flexDirection:'column', gap: 4, minWidth:'100%' }}>
        {/* month row */}
        <div style={{ display:'grid', gridTemplateColumns:`28px repeat(${weeks.length}, 14px)`, columnGap: 3, marginBottom: 2 }}>
          <div/>
          {weeks.map((_, wi) => {
            const lbl = monthLabels.find(m => m.wi === wi);
            return <div key={wi} className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)', letterSpacing:'.04em', height: 12, whiteSpace:'nowrap' }}>{lbl?.label || ''}</div>;
          })}
        </div>
        {/* 7 rows */}
        {[0,1,2,3,4,5,6].map(row => (
          <div key={row} style={{ display:'grid', gridTemplateColumns:`28px repeat(${weeks.length}, 14px)`, columnGap: 3 }}>
            <div className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)', textAlign:'right', paddingRight: 4, height: 14, lineHeight:'14px' }}>
              {row===0?'пн':row===2?'ср':row===4?'пт':row===6?'вс':''}
            </div>
            {weeks.map((w, wi) => {
              const d = w[row];
              if (!d) return <div key={wi}/>;
              const future = d.date > todayISO();
              return (
                <HoverCard key={wi} content={
                  future ? `${fmtDate(d.date)} · скоро` :
                  `${fmtDate(d.date)} · ${d.rating}/5${d.isDefault ? ' (по умолчанию)' : ''}${d.comment ? ` · ${d.comment.slice(0,40)}${d.comment.length>40?'…':''}`:''}`
                }>
                  <button onClick={()=> !future && onCellClick?.(d)}
                    style={{
                      width: 14, height: 14, borderRadius: 4,
                      background: future ? 'transparent' : lvl(d),
                      border: future ? '1px dashed var(--border)' : d.isDefault ? '1px solid rgba(20,18,14,.04)' : 'none',
                      opacity: d.isDefault ? 0.55 : 1,
                      cursor: future ? 'default' : 'pointer', padding: 0,
                      transition:'transform .1s ease'
                    }}
                    onMouseEnter={e=> !future && (e.currentTarget.style.transform='scale(1.25)')}
                    onMouseLeave={e=> (e.currentTarget.style.transform='scale(1)')}
                  />
                </HoverCard>
              );
            })}
          </div>
        ))}
        {/* legend */}
        <div style={{ display:'flex', alignItems:'center', gap: 8, marginTop: 8, paddingLeft: 32 }}>
          <span className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)' }}>МЕНЬШЕ</span>
          {[1,2,3,4,5].map(l => (
            <div key={l} style={{ width: 14, height: 14, borderRadius: 4, background:`var(--level-${l})` }}/>
          ))}
          <span className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)' }}>БОЛЬШЕ</span>
          <div style={{ width: 14, height: 14, borderRadius: 4, border:'1px solid var(--border-strong)', marginLeft: 10, opacity: .55 }}/>
          <span className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)' }}>ПО УМОЛЧАНИЮ</span>
        </div>
      </div>
    </div>
  );
};

// Monthly calendar with rating colored tiles
const MonthCalendar = ({ days, month, year, onPick, selectedDate }) => {
  const firstOfMonth = new Date(year, month, 1);
  const startWd = (firstOfMonth.getDay() + 6) % 7; // Mon-first
  const daysInMonth = new Date(year, month+1, 0).getDate();
  const dayMap = {};
  days.forEach(d => dayMap[d.date] = d);
  const cells = [];
  for (let i = 0; i < startWd; i++) cells.push(null);
  for (let i = 1; i <= daysInMonth; i++) cells.push(i);
  while (cells.length % 7) cells.push(null);
  const weekdays = ['пн','вт','ср','чт','пт','сб','вс'];
  const todayStr = todayISO();

  return (
    <div>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(7, 1fr)', gap: 8, marginBottom: 10 }}>
        {weekdays.map(w => <div key={w} className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)', textAlign:'center', letterSpacing:'.08em', textTransform:'uppercase' }}>{w}</div>)}
      </div>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(7, 1fr)', gap: 8 }}>
        {cells.map((c, i) => {
          if (c === null) return <div key={i} style={{ aspectRatio:'1', minHeight: 48 }}/>;
          const iso = new Date(year, month, c).toISOString().slice(0,10);
          const d = dayMap[iso];
          const isToday = iso === todayStr;
          const isSelected = iso === selectedDate;
          const future = new Date(iso) > new Date(todayStr);
          return (
            <button key={i} disabled={future} onClick={()=> onPick?.(iso)}
              style={{
                aspectRatio:'1', minHeight: 48, borderRadius: 12,
                background: d ? `var(--level-${d.rating})` : 'var(--surface-2)',
                color: d && d.rating <= 3 ? '#fff' : 'var(--fg)',
                opacity: future ? .35 : d?.isDefault ? .55 : 1,
                border: isSelected ? '2px solid var(--fg)' : isToday ? '1.5px solid var(--fg)' : '1px solid transparent',
                padding: 6, display:'flex', flexDirection:'column', alignItems:'flex-start', justifyContent:'space-between',
                cursor: future ? 'not-allowed' : 'pointer', textAlign:'left',
                transition:'transform .12s ease, border-color .15s ease',
                position:'relative'
              }}
              onMouseEnter={e=> !future && (e.currentTarget.style.transform='scale(1.04)')}
              onMouseLeave={e=> (e.currentTarget.style.transform='scale(1)')}
            >
              <span style={{ fontSize: 13, fontWeight: 600 }}>{c}</span>
              {d && <span style={{ fontSize: 10, fontWeight: 500, opacity: .9 }}>{'★'.repeat(d.rating)}</span>}
              {d?.comment && <div style={{ position:'absolute', top: 5, right: 6, width: 5, height: 5, borderRadius: 5, background: d.rating<=3?'#fff':'var(--fg)' }}/>}
            </button>
          );
        })}
      </div>
    </div>
  );
};

// Simple bar chart (rating distribution)
const BarChart = ({ data, height=140, color='var(--accent)' }) => {
  const max = Math.max(...data.map(d => d.value), 1);
  return (
    <div style={{ display:'flex', alignItems:'flex-end', gap: 8, height, padding: '0 4px' }}>
      {data.map((d, i) => {
        const h = (d.value / max) * (height - 28);
        return (
          <div key={i} style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', gap: 6 }}>
            <div className="mono" style={{ fontSize: 10, color:'var(--fg-muted)' }}>{d.value}</div>
            <div style={{ width:'100%', height: h, background: d.color || color, borderRadius: '6px 6px 0 0', transition:'height .4s ease' }}/>
            <div className="mono" style={{ fontSize: 10, color:'var(--fg-subtle)' }}>{d.label}</div>
          </div>
        );
      })}
    </div>
  );
};

// Line / area chart — weekly average trend
const TrendChart = ({ points, height=160 }) => {
  if (!points || points.length < 2) return null;
  const w = 560, h = height;
  const pad = { t: 16, r: 12, b: 24, l: 28 };
  const min = 1, max = 5;
  const xs = (i) => pad.l + (i/(points.length-1)) * (w - pad.l - pad.r);
  const ys = (v) => pad.t + (1 - (v-min)/(max-min)) * (h - pad.t - pad.b);
  const linePath = points.map((p,i)=> `${i===0?'M':'L'} ${xs(i).toFixed(1)} ${ys(p.v).toFixed(1)}`).join(' ');
  const areaPath = `${linePath} L ${xs(points.length-1).toFixed(1)} ${h - pad.b} L ${xs(0).toFixed(1)} ${h - pad.b} Z`;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} style={{ width:'100%', height }}>
      {/* grid */}
      {[1,2,3,4,5].map(v => (
        <g key={v}>
          <line x1={pad.l} x2={w - pad.r} y1={ys(v)} y2={ys(v)} stroke="var(--border)" strokeDasharray={v===3?'':'2 4'}/>
          <text x={pad.l - 8} y={ys(v)+3} fontSize="10" fill="var(--fg-subtle)" textAnchor="end" className="mono">{v}</text>
        </g>
      ))}
      <defs>
        <linearGradient id="areaG" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.18"/>
          <stop offset="100%" stopColor="var(--accent)" stopOpacity="0"/>
        </linearGradient>
      </defs>
      <path d={areaPath} fill="url(#areaG)"/>
      <path d={linePath} fill="none" stroke="var(--accent)" strokeWidth="2" strokeLinejoin="round" strokeLinecap="round"/>
      {points.map((p, i) => (
        <g key={i}>
          <circle cx={xs(i)} cy={ys(p.v)} r={3.5} fill="var(--surface)" stroke="var(--accent)" strokeWidth="2"/>
          {i % Math.ceil(points.length/6) === 0 && (
            <text x={xs(i)} y={h - 6} fontSize="10" fill="var(--fg-subtle)" textAnchor="middle" className="mono">{p.label}</text>
          )}
        </g>
      ))}
    </svg>
  );
};

// Streak sparkline
const Sparkline = ({ values, color='var(--accent)', w=120, h=32 }) => {
  if (!values || values.length < 2) return <svg width={w} height={h} style={{ display:'block' }}/>;
  const max = Math.max(...values, 1);
  const pts = values.map((v, i) => `${(i/(values.length-1))*w},${h - (v/max)*(h-4) - 2}`).join(' ');
  return (
    <svg viewBox={`0 0 ${w} ${h}`} width={w} height={h} style={{ display:'block' }}>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.8" strokeLinejoin="round" strokeLinecap="round"/>
    </svg>
  );
};

Object.assign(window, { Heatmap, MonthCalendar, BarChart, TrendChart, Sparkline });
