// redesign/data.jsx — Live data layer.
// Fetches from real /api/* endpoints and computes derived UI shapes.

const { useState: useState_D, useEffect: useEffect_D, useCallback: useCallback_D, useRef: useRef_D } = React;

const EMPTY_DATA = {
  STATS: { keywords: 0, batches: 0, blocked: 0, templatesCompleted: 0, gradesS: 0, gradesA: 0, gradesB: 0, gradesC: 0, feedbackRate: 0 },
  STATUS: { autosourcing: false, templateWorker: false, stage: null, keyword: null },
  KEYWORDS: [],
  SA_TOP: [],
  QUEUE: [],
  FAILED_QUEUE: [],
  PATTERNS: [],
  CONFIG: { duplicateCheckDays: 90, defaultBatchCount: 3, nightScheduleEnabled: true, flags: {} },
  HUD_METRICS: [],
  STAGE_STEPS: [],
  GRADE_DIST: [],
  WEEKLY: [],
  ACTIVITY: [],
  HISTORY: [],
  loading: true,
  error: null,
};

const PIPELINE_DEFS = [
  { id: 0, label: "시드 선택",   desc: "키워드 큐" },
  { id: 1, label: "검색 수집",   desc: "쿠팡 검색" },
  { id: 2, label: "상세 수집",   desc: "상세 페이지" },
  { id: 3, label: "리뷰 수집",   desc: "부정 리뷰" },
  { id: 4, label: "Qwen 필터",  desc: "L1/L2" },
  { id: 5, label: "수요 검증",   desc: "뱃지/로켓" },
  { id: 6, label: "Opus 판정",  desc: "S/A/B/C" },
  { id: 7, label: "기획서",     desc: "template" },
  { id: 8, label: "완료",       desc: "DB 저장" },
];

function adaptStats(s) {
  if (!s) return EMPTY_DATA.STATS;
  return {
    keywords: s.keywords || 0,
    batches: s.batches || 0,
    blocked: s.blocked || 0,
    templatesCompleted: s.templatesCompleted || 0,
    gradesS: (s.grades && s.grades.S) || 0,
    gradesA: (s.grades && s.grades.A) || 0,
    gradesB: (s.grades && s.grades.B) || 0,
    gradesC: (s.grades && s.grades.C) || 0,
    feedbackRate: (s.feedbackRate && s.feedbackRate.pct) || 0,
  };
}

function adaptKeywords(rows) {
  if (!Array.isArray(rows)) return [];
  return rows.map(r => ({
    kw: r.keyword,
    grade: r.grade,
    score: r.score || 0,
    rocketPct: r.rocketRatio || 0,
    sellerRocketPct: 0,
    sellerRocketCount: r.sellerRocketCount || 0,
    killer: r.killerFeature || '',
    pain: r.commonPain || '',
    outcome: r.actualOutcome,
    revenue: r.actualRevenue,
    notes: r.notes || '',
    date: (r.createdAt || '').slice(0, 10),
    lastTemplateAt: r.lastTemplateAt,
    templateAgeHours: r.templateAgeHours,
    avgPrice: r.avgPrice,
    avgReviews: r.avgReviews,
    sparkline: Array.from({ length: 8 }, () => Math.max(0, (r.score || 50) + (Math.random() - 0.5) * 20)),
  }));
}

function adaptQueue(q) {
  if (!q) return { QUEUE: [], FAILED_QUEUE: [] };
  const fmt = (item) => ({
    file: item.filename,
    kw: item.keyword,
    grade: item.grade,
    score: item.score || 0,
    time: item.ts ? new Date(item.ts).toLocaleString('ko-KR', { hour12: false }).slice(5, 16) : '-',
    reason: item.reason || '',
  });
  return {
    QUEUE: (q.pending || []).map(fmt),
    FAILED_QUEUE: (q.failed || []).map(fmt),
  };
}

function adaptStatus(s) {
  if (!s) return EMPTY_DATA.STATUS;
  const as = s.autosourcing || {};
  const tw = s.templateWorker || {};
  return {
    autosourcing: !!(as.running),
    templateWorker: !!(tw.running),
    stage: as.stage || null,
    keyword: as.keyword || null,
    elapsedSec: as.elapsedSec || null,
    queuePending: tw.queuePending || 0,
    twKeyword: tw.keyword || null,
  };
}

function buildHudMetrics(stats) {
  const total = stats.keywords;
  const sa = stats.gradesS + stats.gradesA;
  const rate = total > 0 ? (sa / total * 100).toFixed(1) : '0';
  return [
    { label: "오늘 분석", value: total, trend: total > 0 ? "up" : "flat", delta: `+${total}`, emphasis: "accent" },
    { label: "S/A 통과", value: sa, trend: sa > 0 ? "up" : "flat", delta: `${sa}건` },
    { label: "통과율", value: rate + '%', trend: +rate > 15 ? "up" : "down", delta: rate + '%' },
    { label: "배치 수", value: stats.batches, trend: "flat", delta: '' },
    { label: "피드백율", value: stats.feedbackRate + '%', trend: stats.feedbackRate > 50 ? "up" : "down", delta: stats.feedbackRate + '%' },
  ];
}

function buildStageSteps(status) {
  if (!status.autosourcing) {
    return PIPELINE_DEFS.map(d => ({ ...d, state: "pending" }));
  }
  const stageMatch = (status.stage || '').match(/\[(\d)\/(\d)\]/);
  const current = stageMatch ? parseInt(stageMatch[1]) : -1;
  return PIPELINE_DEFS.map(d => ({
    ...d,
    state: d.id < current ? "done" : d.id === current ? "active" : "pending",
  }));
}

function buildGradeDist(stats) {
  const total = stats.gradesS + stats.gradesA + stats.gradesB + stats.gradesC;
  if (total === 0) return ['S','A','B','C'].map(g => ({ grade: g, count: 0, pct: 0 }));
  return [
    { grade: "S", count: stats.gradesS, pct: stats.gradesS / total * 100 },
    { grade: "A", count: stats.gradesA, pct: stats.gradesA / total * 100 },
    { grade: "B", count: stats.gradesB, pct: stats.gradesB / total * 100 },
    { grade: "C", count: stats.gradesC, pct: stats.gradesC / total * 100 },
  ];
}

function buildWeekly(weeklyData) {
  const dayNames = ['일','월','화','수','목','금','토'];
  if (!weeklyData || !weeklyData.days || weeklyData.days.length === 0) {
    return Array.from({ length: 7 }, (_, i) => {
      const d = new Date(); d.setDate(d.getDate() - 6 + i);
      return { day: dayNames[d.getDay()], batches: 0, sa: 0 };
    });
  }
  return weeklyData.days.map(d => ({
    day: dayNames[new Date(d.date + 'T00:00:00').getDay()],
    batches: d.processed || 0,
    sa: d.passed || 0,
  }));
}

function buildActivity(keywords, status) {
  const items = [];
  if (status.autosourcing && status.keyword) {
    items.push({ icon: "⚡", title: `분석 중: ${status.keyword}`, detail: status.stage || '진행중', time: "now", state: "active" });
  }
  if (status.templateWorker && status.twKeyword) {
    items.push({ icon: "📄", title: `기획서: ${status.twKeyword}`, detail: "template_worker", time: "now", state: "active" });
  }
  for (const kw of keywords.slice(0, 8)) {
    const icon = kw.grade === 'S' ? '🏆' : kw.grade === 'A' ? '✅' : '📋';
    const ageH = kw.templateAgeHours;
    let time = kw.date;
    if (ageH != null && ageH < 24) time = `${ageH}h 전`;
    items.push({ icon, title: `${kw.kw} — ${kw.grade} ${kw.score}점`, detail: kw.killer || '', time, state: kw.grade === 'S' || kw.grade === 'A' ? 'done' : 'pending' });
  }
  return items.slice(0, 10);
}

function adaptPatterns(raw) {
  if (!Array.isArray(raw)) return [];
  return raw.map((p, i) => ({
    title: p.metric || p.title || '-',
    weight: typeof p.weight === 'number' ? p.weight : Math.max(0.1, 1 - i * 0.12),
    samples: p.samples || p.value || '-',
    trend: p.trend || 'flat',
  }));
}

function useDashData() {
  const [data, setData] = useState_D(EMPTY_DATA);

  const refetch = useCallback_D(async () => {
    try {
      const [stats, status, recent, queue, patterns, config, weekly] = await Promise.all([
        AS_API.statsToday().catch(() => null),
        AS_API.status().catch(() => null),
        AS_API.recentSA(15).catch(() => []),
        AS_API.queue().catch(() => null),
        AS_API.patterns().catch(() => []),
        AS_API.config().catch(() => null),
        AS_API.statsWeekly().catch(() => null),
      ]);

      const st = adaptStats(stats);
      const su = adaptStatus(status);
      const kws = adaptKeywords(recent);
      const q = adaptQueue(queue);

      setData({
        STATS: st,
        STATUS: su,
        KEYWORDS: kws,
        SA_TOP: kws,
        QUEUE: q.QUEUE,
        FAILED_QUEUE: q.FAILED_QUEUE,
        PATTERNS: adaptPatterns(patterns),
        CONFIG: config || EMPTY_DATA.CONFIG,
        HUD_METRICS: buildHudMetrics(st),
        STAGE_STEPS: buildStageSteps(su),
        GRADE_DIST: buildGradeDist(st),
        WEEKLY: buildWeekly(weekly),
        ACTIVITY: buildActivity(kws, su),
        HISTORY: kws,
        loading: false,
        error: null,
      });
    } catch (e) {
      setData(d => ({ ...d, loading: false, error: e.message || String(e) }));
    }
  }, []);

  useEffect_D(() => {
    refetch();
    const fast = setInterval(async () => {
      const [status, queue] = await Promise.all([
        AS_API.status().catch(() => null),
        AS_API.queue().catch(() => null),
      ]);
      const su = adaptStatus(status);
      const q = adaptQueue(queue);
      setData(d => ({ ...d, STATUS: su, QUEUE: q.QUEUE, FAILED_QUEUE: q.FAILED_QUEUE, STAGE_STEPS: buildStageSteps(su) }));
    }, 5000);
    const slow = setInterval(refetch, 30000);
    const onVis = () => { if (!document.hidden) refetch(); };
    document.addEventListener('visibilitychange', onVis);
    return () => { clearInterval(fast); clearInterval(slow); document.removeEventListener('visibilitychange', onVis); };
  }, [refetch]);

  return [data, refetch];
}

Object.assign(window, { useDashData, EMPTY_DATA });
