// Reviews dashboard

const CHART_CATS = ["#2EB89B","#4A8CC4","#F5A623","#A67DB8","#E07A5F","#6B8F6B","#3B7080","#C98A5E"];

function LineChart({ data, height = 220 }) {
  const w = 100, h = 100;
  const max = Math.max(...data.map(d => d.v));
  const pts = data.map((d, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - (d.v / max) * h * 0.9 - 4;
    return [x, y];
  });
  const path = pts.map((p, i) => (i === 0 ? "M" : "L") + p[0].toFixed(2) + "," + p[1].toFixed(2)).join(" ");
  const area = path + ` L${w},${h} L0,${h} Z`;
  return (
    <svg className="chart-svg" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{height}}>
      <defs>
        <linearGradient id="lineGrad" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.25" />
          <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
        </linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map((t, i) => (
        <line key={i} x1="0" x2={w} y1={h*t} y2={h*t} stroke="var(--chart-grid)" strokeWidth="0.3" />
      ))}
      <path d={area} fill="url(#lineGrad)" />
      <path d={path} fill="none" stroke="var(--accent)" strokeWidth="0.8" strokeLinejoin="round" strokeLinecap="round" />
      {pts.map((p, i) => i % 4 === 0 && (
        <circle key={i} cx={p[0]} cy={p[1]} r="0.7" fill="var(--accent)" />
      ))}
    </svg>
  );
}

function Donut({ data, size = 200 }) {
  const total = data.reduce((s, d) => s + d.count, 0);
  const radius = 40, cx = 50, cy = 50;
  let angle = -Math.PI / 2;
  const arcs = data.map(d => {
    const a = (d.count / total) * Math.PI * 2;
    const x1 = cx + radius * Math.cos(angle);
    const y1 = cy + radius * Math.sin(angle);
    const x2 = cx + radius * Math.cos(angle + a);
    const y2 = cy + radius * Math.sin(angle + a);
    const large = a > Math.PI ? 1 : 0;
    const path = `M${cx},${cy} L${x1.toFixed(2)},${y1.toFixed(2)} A${radius},${radius} 0 ${large} 1 ${x2.toFixed(2)},${y2.toFixed(2)} Z`;
    angle += a;
    return { ...d, path };
  });
  return (
    <svg viewBox="0 0 100 100" width={size} height={size}>
      {arcs.map((a, i) => (
        <path key={i} d={a.path} fill={a.color} stroke="var(--bg-surface)" strokeWidth="1" />
      ))}
      <circle cx={cx} cy={cy} r="22" fill="var(--bg-surface)" />
      <text x="50" y="48" textAnchor="middle" fontSize="8" fontWeight="700" fill="var(--fg-default)" fontFamily="var(--font-mono)">{total.toLocaleString("ko-KR")}</text>
      <text x="50" y="58" textAnchor="middle" fontSize="4" fill="var(--fg-muted)">리뷰</text>
    </svg>
  );
}

function heatColor(val, max) {
  const ratio = val / max;
  if (val === 0) return "var(--heat-0)";
  if (ratio < 0.2) return "var(--heat-1)";
  if (ratio < 0.4) return "var(--heat-2)";
  if (ratio < 0.6) return "var(--heat-3)";
  if (ratio < 0.8) return "var(--heat-4)";
  return "var(--heat-5)";
}

/* Clean SVG icons replacing filter emojis */
const FilterIcon = {
  country: (
    <svg viewBox="0 0 20 20" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5">
      <circle cx="10" cy="10" r="7.5" />
      <path d="M2.5 10h15M10 2.5c2.5 2.5 2.5 12.5 0 15M10 2.5c-2.5 2.5-2.5 12.5 0 15" />
    </svg>
  ),
  star: (
    <svg viewBox="0 0 20 20" width="14" height="14" fill="currentColor">
      <path d="M10 2l2.5 5.1 5.6.8-4 3.9.9 5.6-5-2.6-5 2.6.9-5.6-4-3.9 5.6-.8z" />
    </svg>
  ),
  lang: (
    <svg viewBox="0 0 20 20" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5">
      <path d="M3 5h7M6.5 3v2M4 5c0 3 1.5 6 4 7M8 8c-1 3-3 5-5 6" strokeLinecap="round" />
      <path d="M11 17l3-8 3 8M12 14.5h4" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  ),
  search: (
    <svg viewBox="0 0 20 20" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.5">
      <circle cx="9" cy="9" r="5.5" />
      <path d="M13 13l4 4" strokeLinecap="round" />
    </svg>
  ),
};

function ReviewsKpiRich({ data, chart }) {
  // 1) total reviews w/ spark
  // 2) avg rating with star distribution
  // 3) reply rate with donut
  // 4) foreign rate with mini flags
  const replyPct = 60.7;
  const foreignPct = 6.9;
  return (
    <div className="kpi-grid kpi-grid-rich">
      <EnhancedKpi
        value={2200}
        label="총 리뷰"
        format="exact"
        annotation="2018 Q2 정점 198건"
        extra={
          <div className="kpi-mini">
            <SparkMini data={chart.monthlyReviews.map(m => m.v)} />
            <div className="kpi-mini-axis"><span>16</span><span>18</span><span>20</span><span>23</span></div>
          </div>
        }
      />
      <EnhancedKpi
        value={3.84}
        label="평균 별점"
        format="rating"
        annotation="5점 57.4% · 1점 5.6%"
        extra={<StarDistMini />}
      />
      <EnhancedKpi
        value={60.7}
        label="개발자 답변율"
        format="percent"
        annotation="2,200건 중 1,335건"
        extra={<ReplyRateMini pct={replyPct} />}
      />
      <EnhancedKpi
        value={6.9}
        label="외국어 리뷰"
        format="percent"
        annotation="2,200건 중 153건"
        extra={<FlagCloudMini />}
      />
    </div>
  );
}

function ReplyRateMini({ pct }) {
  const [ref, inView] = useInView();
  const R = 22, C = 2 * Math.PI * R;
  const offset = inView ? C - (pct / 100) * C : C;
  return (
    <div ref={ref} className="kpi-reply">
      <svg viewBox="0 0 60 60" width="68" height="68">
        <circle cx="30" cy="30" r={R} fill="none" stroke="var(--bg-surface-alt)" strokeWidth="6" />
        <circle
          cx="30" cy="30" r={R}
          fill="none"
          stroke="var(--accent)"
          strokeWidth="6"
          strokeLinecap="round"
          strokeDasharray={C}
          strokeDashoffset={offset}
          transform="rotate(-90 30 30)"
          style={{ transition: "stroke-dashoffset 1100ms cubic-bezier(.2,.9,.2,1)" }}
        />
        <text x="30" y="34" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--fg-default)" fontFamily="var(--font-mono)">{pct.toFixed(0)}%</text>
      </svg>
      <div className="kpi-reply-legend">
        <div><span className="dot dot-accent" />답변 있음 · 1,335</div>
        <div><span className="dot dot-muted" />답변 없음 · 865</div>
      </div>
    </div>
  );
}

function ReviewsPage({ openReview }) {
  const data = window.ARCHIVE_DATA;
  const chartData = window.CHART_DATA;
  const allReviews = window.REVIEW_LIST;

  const [filters, setFilters] = React.useState({
    countries: new Set(chartData.topCountries.map(c => c.code)),
    ratings: new Set([1,2,3,4,5]),
    lang: "all",
    keyword: "",
  });

  const filtered = React.useMemo(() => {
    return allReviews.filter(r => {
      const code = r.flag === "🇰🇷" ? "KR" : r.flag === "🇺🇸" ? "US" : r.flag === "🇹🇼" ? "TW" : r.flag === "🇯🇵" ? "JP" : r.flag === "🇨🇳" ? "CN" : "OTHER";
      if (!filters.countries.has(code) && code !== "OTHER") return false;
      if (!filters.ratings.has(r.rating)) return false;
      if (filters.lang === "ko" && r.lang !== "KO") return false;
      if (filters.lang === "foreign" && r.lang === "KO") return false;
      if (filters.keyword && !(r.title + " " + r.body).toLowerCase().includes(filters.keyword.toLowerCase())) return false;
      return true;
    });
  }, [filters, allReviews]);

  const toggleSet = (key, val) => {
    setFilters(f => {
      const s = new Set(f[key]);
      if (s.has(val)) s.delete(val); else s.add(val);
      return { ...f, [key]: s };
    });
  };

  const reset = () => setFilters({
    countries: new Set(chartData.topCountries.map(c => c.code)),
    ratings: new Set([1,2,3,4,5]),
    lang: "all",
    keyword: "",
  });

  const maxHeat = Math.max(...chartData.heatmap.flatMap(r => r.data));

  return (
    <div className="page">
      <section className="reviews-hero">
        <h1>리뷰</h1>
        <p className="reviews-hero-sub">2,200개의 목소리, 7년 5개월</p>
      </section>

      <section>
        <ReviewsKpiRich data={data} chart={chartData} />
      </section>

      <section className="section" style={{marginTop: 72}}>
        <Narrative>
          {data.narrative.reviewsIntro.map((p, i) => <p key={i}>{p}</p>)}
        </Narrative>
      </section>

      <div className="reviews-layout">
        <aside className="filter-sidebar">
          <div className="filter-header">
            <h3>필터</h3>
            <button className="filter-reset" onClick={reset}>초기화</button>
          </div>

          <div className="filter-section">
            <div className="filter-section-title"><span className="filter-ico">{FilterIcon.country}</span> 국가 ({chartData.topCountries.length})</div>
            {chartData.topCountries.slice(0, 6).map(c => (
              <div key={c.code} className="checkbox-item" onClick={() => toggleSet("countries", c.code)}>
                <div style={{display:"flex",alignItems:"center",gap:8}}>
                  <div className={"checkbox-box" + (filters.countries.has(c.code) ? " checked" : "")}></div>
                  <span>{c.flag} {c.name}</span>
                </div>
                <span className="checkbox-count">{c.count.toLocaleString("ko-KR")}</span>
              </div>
            ))}
          </div>

          <div className="filter-section">
            <div className="filter-section-title"><span className="filter-ico">{FilterIcon.star}</span> 별점</div>
            <div className="rating-toggle">
              {[1,2,3,4,5].map(r => (
                <button
                  key={r}
                  className={"rating-pill" + (filters.ratings.has(r) ? " active" : "")}
                  onClick={() => toggleSet("ratings", r)}
                >{r}</button>
              ))}
            </div>
          </div>

          <div className="filter-section">
            <div className="filter-section-title"><span className="filter-ico">{FilterIcon.lang}</span> 언어</div>
            {[{v:"all",l:"전체"},{v:"ko",l:"한국어"},{v:"foreign",l:"외국어"}].map(opt => (
              <div key={opt.v} className="checkbox-item" onClick={() => setFilters(f => ({...f, lang: opt.v}))}>
                <div style={{display:"flex",alignItems:"center",gap:8}}>
                  <div className="checkbox-box" style={{borderRadius:"50%", background: filters.lang === opt.v ? "var(--accent)" : "var(--bg-surface)", borderColor: filters.lang === opt.v ? "var(--accent)" : "var(--border-strong)"}}>
                    {filters.lang === opt.v && <div style={{width:6,height:6,borderRadius:"50%",background:"white"}}></div>}
                  </div>
                  <span>{opt.l}</span>
                </div>
              </div>
            ))}
          </div>

          <div className="filter-section">
            <div className="filter-section-title"><span className="filter-ico">{FilterIcon.search}</span> 키워드</div>
            <input
              className="filter-input"
              type="text"
              value={filters.keyword}
              placeholder="본문에서 검색"
              onChange={(e) => setFilters(f => ({...f, keyword: e.target.value}))}
            />
          </div>
        </aside>

        <div>
          <div className="chart-grid">
            <div className="chart-card">
              <div className="chart-card-head">
                <h4 className="chart-title">월간 리뷰 추이</h4>
                <span className="caption muted">분기 집계</span>
              </div>
              <p className="chart-sub">2016 Q1 ~ 2023 Q4 · 2018년 2분기 정점 198건</p>
              <LineChart data={chartData.monthlyReviews} height={240} />
              <div style={{display:"flex", justifyContent:"space-between", marginTop: 8, fontSize: 11, color:"var(--fg-subtle)", fontFamily:"var(--font-mono)"}}>
                <span>2016</span><span>2018</span><span>2020</span><span>2022</span><span>2023</span>
              </div>
            </div>

            <div className="charts-row">
              <div className="chart-card">
                <div className="chart-card-head">
                  <h4 className="chart-title" style={{"--accent": CHART_CATS[2]}}>별점 분포</h4>
                </div>
                <p className="chart-sub">평균 ★ 3.84</p>
                <div style={{display:"flex", alignItems:"center", gap:16, marginTop:8}}>
                  <Donut data={chartData.ratingDist} size={160} />
                  <div className="donut-legend" style={{flex:1}}>
                    {chartData.ratingDist.map(r => (
                      <div key={r.rating} className="donut-row">
                        <div className="donut-dot" style={{background: r.color}}></div>
                        <div>{r.rating}점</div>
                        <div className="mono" style={{color:"var(--fg-muted)"}}>{r.pct}%</div>
                        <div className="mono" style={{color:"var(--fg-subtle)",fontSize:11}}>{r.count.toLocaleString("ko-KR")}</div>
                      </div>
                    ))}
                  </div>
                </div>
              </div>

              <div className="chart-card">
                <div className="chart-card-head">
                  <h4 className="chart-title">국가 Top 10</h4>
                </div>
                <p className="chart-sub">대한민국이 90%</p>
                <div className="bar-list">
                  {chartData.topCountries.map((c, i) => {
                    const max = chartData.topCountries[0].count;
                    return (
                      <div key={c.code} className="bar-row">
                        <div className="bar-label">
                          <span>{c.flag}</span>
                          <span style={{fontSize:12}}>{c.name}</span>
                        </div>
                        <div className="bar-track">
                          <div className="bar-fill" style={{width: `${(c.count / max) * 100}%`, transitionDelay: `${i * 40}ms`}}></div>
                        </div>
                        <div className="bar-count">{c.count.toLocaleString("ko-KR")}</div>
                      </div>
                    );
                  })}
                </div>
              </div>
            </div>

            <div className="chart-card">
              <div className="chart-card-head">
                <h4 className="chart-title">연도 × 별점 히트맵</h4>
                <span className="caption muted">셀 호버로 상세</span>
              </div>
              <p className="chart-sub">별이 가장 진하게 찍힌 시기는 2017 – 2018</p>
              <div style={{marginTop: 16}}>
                <div className="heatmap-header">
                  {chartData.heatmapYears.map(y => (
                    <div key={y} className="heatmap-header-cell">{y}</div>
                  ))}
                </div>
                {chartData.heatmap.map(row => (
                  <div key={row.label} className="heatmap-row">
                    <div className="heatmap-label">{row.label}</div>
                    {row.data.map((val, i) => (
                      <div key={i} className="heatmap-cell" style={{background: heatColor(val, maxHeat)}} title={`${chartData.heatmapYears[i]} · ${row.label} · ${val}건`}></div>
                    ))}
                  </div>
                ))}
              </div>
              <div style={{display:"flex", justifyContent:"flex-end", alignItems:"center", gap:6, marginTop:16, fontSize:11, color:"var(--fg-muted)"}}>
                <span>적음</span>
                {[0,1,2,3,4,5].map(i => (
                  <div key={i} style={{width:14, height:14, background: `var(--heat-${i})`, borderRadius:3}}></div>
                ))}
                <span>많음</span>
              </div>
            </div>

            <div className="callout-box">
              <div style={{fontSize:18, lineHeight:1}}>⚠</div>
              <div>
                <strong>Apple API 제약</strong> — 월별 트랜잭션은 최근 12개월만 제공됩니다. 2016 – 2022년 데이터는 분기 집계로 표시됩니다.
              </div>
            </div>
          </div>

          <div style={{marginTop: 48}}>
            <div className="review-list-head">
              <div className="review-list-count">
                전체 리뷰 (필터 결과: <strong>{filtered.length}</strong>건)
              </div>
              <span className="caption muted">정렬: 최신순</span>
            </div>

            {filtered.length === 0 ? (
              <div className="empty-state">
                <div className="empty-state-icon">🍃</div>
                <div className="empty-state-title">이 조합에 해당하는 리뷰가 남아있지 않습니다</div>
                <div className="empty-state-sub">필터를 조금 풀어보면 다른 이야기가 나타날지도 몰라요.</div>
                <button className="btn btn-ghost" onClick={reset} style={{marginTop:20}}>필터 초기화</button>
              </div>
            ) : (
              filtered.map(r => {
                const stars = "★".repeat(r.rating) + "☆".repeat(5-r.rating);
                return (
                  <button key={r.id} className="review-list-item" onClick={() => openReview(r)}>
                    <span className="review-list-stars">{stars}</span>
                    <span className="review-list-flag">{r.flag}</span>
                    <div className="review-list-body">
                      <div className="review-list-title">{r.title}</div>
                      <div className="review-list-snippet">{r.body}</div>
                    </div>
                    <div className="review-list-meta">
                      <span>{r.date}</span>
                      {r.lang !== "KO" && <span className="badge badge-lang">{r.lang}</span>}
                    </div>
                  </button>
                );
              })
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { ReviewsPage });
