// HR-03 · 분기 펄스서베이 + AI 감성 분석
// 난이도 ★★ · 예상 45분 · 전제: Google Form + Gemini API 키
// 출처: https://www.nedabah.org/resources/automation/hr/03-pulse-survey-sentiment.html
// Apps Script 편집기에 붙여넣은 뒤 스크립트 속성에 PROPS 항목을 등록하세요.

const PROPS = PropertiesService.getScriptProperties();
const SHEET_ID   = PROPS.getProperty('RESPONSE_SHEET_ID');
const GEMINI_KEY = PROPS.getProperty('GEMINI_API_KEY');
const EMAIL_TO   = PROPS.getProperty('RECIPIENT_EMAIL');

// 응답 시트 1-base 컬럼 인덱스
// A(1)=Timestamp, B(2)=직군, C(3)=몰입(1~5), D(4)=ENPS(0~10),
// E(5)=잘된 점, F(6)=답답한 점, G(7)=자유 의견
const GROUP_COL = 2;          // 직군 (B열)
const TEXT_COLS = [5, 6, 7];  // 정성 응답 컬럼 인덱스 — AI에 전송되는 유일한 데이터

// ─────────────────────────────────────────────
// 1) 응답 일괄 분석
// ─────────────────────────────────────────────
function analyzeAll() {
  const ss  = SpreadsheetApp.openById(SHEET_ID);
  const src = ss.getSheets()[0];
  const dst = ss.getSheetByName('analyzed') || ss.insertSheet('analyzed');
  if (dst.getLastRow() === 0) dst.appendRow(['행', '직군', '감성', '주제', '요지']);

  const data = src.getDataRange().getValues();
  const processed = new Set(dst.getRange('A2:A').getValues().flat().map(String));

  const batch = []; // [{row, group, text}]
  for (let i = 1; i < data.length; i++) {
    if (processed.has(String(i+1))) continue;
    const group = data[i][GROUP_COL - 1]; // 직군 (B열, 1-base index 2)
    const merged = TEXT_COLS.map(c => String(data[i][c-1] || '').trim()).filter(Boolean).join(' / ');
    if (!merged) continue;
    batch.push({row: i+1, group, text: merged});
  }
  if (batch.length === 0) return;

  // 50건씩 배치 처리
  for (let i = 0; i < batch.length; i += 50) {
    const slice = batch.slice(i, i+50);
    const result = classifyBatch(slice);
    slice.forEach((b, idx) => {
      const r = result[idx] || {};
      dst.appendRow([b.row, b.group, r.sentiment || '중립', (r.topics||[]).join(','), r.gist || '']);
    });
    Utilities.sleep(2000);
  }
}

function classifyBatch(items) {
  // 식별정보 분리: text만 전송, group은 후처리
  const prompt = `
각 응답에 대해 한국어로 분석하세요. JSON 배열만 반환.
- sentiment: positive/negative/neutral
- topics: 1~3개 주제(짧은 한국어 명사구) — 회사문화/보상/성장/리더십/업무량/복지/관계/제도/도구/번아웃 등에서 자유롭게
- gist: 한 문장 요약(15자 이내)

응답:
${items.map((it,i)=>`[${i+1}] ${it.text}`).join('\n')}

반환 형식: [{"sentiment":"...","topics":["..."],"gist":"..."}]
`;
  const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${GEMINI_KEY}`;
  const res = UrlFetchApp.fetch(url, {
    method:'post', contentType:'application/json',
    payload: JSON.stringify({
      contents:[{parts:[{text: prompt}]}],
      generationConfig:{responseMimeType:'application/json'}
    })
  });
  return JSON.parse(JSON.parse(res.getContentText()).candidates[0].content.parts[0].text);
}

// ─────────────────────────────────────────────
// 2) 1페이지 경영진 리포트
// ─────────────────────────────────────────────
function buildReport() {
  const ss = SpreadsheetApp.openById(SHEET_ID);
  const src = ss.getSheets()[0];
  const ana = ss.getSheetByName('analyzed').getDataRange().getValues();

  // 정량
  const all = src.getDataRange().getValues();
  // Forms는 첫 컬럼에 Timestamp를 자동 추가하므로 ENPS는 D열(1-base 4)에 위치한다.
  const enpsCol = 4;
  const enpsScores = all.slice(1).map(r => Number(r[enpsCol-1])).filter(n => !isNaN(n));
  const enps = enpsScore(enpsScores);

  // 정성: 주제 카운트 + 감성 비율
  const topicCount = {}, byTopicSamples = {};
  let pos = 0, neg = 0, neu = 0;
  for (let i = 1; i < ana.length; i++) {
    const sentiment = ana[i][2];
    const topics = String(ana[i][3]).split(',').map(s => s.trim()).filter(Boolean);
    const gist = ana[i][4];
    topics.forEach(t => {
      topicCount[t] = (topicCount[t]||0) + 1;
      byTopicSamples[t] = byTopicSamples[t] || [];
      if (byTopicSamples[t].length < 3) byTopicSamples[t].push(gist);
    });
    if (sentiment === 'positive') pos++;
    else if (sentiment === 'negative') neg++;
    else neu++;
  }

  const topTopics = Object.entries(topicCount).sort((a,b)=>b[1]-a[1]).slice(0, 6);
  const insight = aiExecutiveSummary(enps, {pos, neg, neu}, topTopics, byTopicSamples);

  const html = renderReport(enps, {pos, neg, neu}, topTopics, byTopicSamples, insight);
  if (EMAIL_TO) GmailApp.sendEmail(EMAIL_TO, `[펄스서베이] ${new Date().toISOString().slice(0,10)} 분석 리포트`, '', {htmlBody: html});

  const rep = ss.getSheetByName('report') || ss.insertSheet('report');
  rep.appendRow([new Date(), enps, JSON.stringify(insight)]);
}

function enpsScore(scores) {
  if (!scores.length) return 0;
  const promoters = scores.filter(s => s >= 9).length;
  const detractors = scores.filter(s => s <= 6).length;
  return Math.round((promoters - detractors) / scores.length * 100);
}

function aiExecutiveSummary(enps, sent, topTopics, samples) {
  const ctx = topTopics.map(([t,c]) => `- ${t}(${c}건): ${(samples[t]||[]).join(' | ')}`).join('\n');
  const prompt = `
당신은 CHRO 코치입니다. 분기 펄스서베이 결과로 경영진용 한 페이지 코멘트를 작성하세요.

데이터:
- ENPS: ${enps}
- 감성 분포: 긍정 ${sent.pos} / 부정 ${sent.neg} / 중립 ${sent.neu}
- 상위 주제:
${ctx}

규칙:
- 추측 금지, 데이터 기반
- 250자 이내
- 1) 가장 시급한 주제 1건과 권고 행동 2개  2) 칭찬할 강점 1건  3) 다음 분기 측정 제안 1건
JSON: {"urgent":"...","actions":["...","..."],"strength":"...","next":"..."}
`;
  const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${GEMINI_KEY}`;
  const res = UrlFetchApp.fetch(url, {method:'post', contentType:'application/json',
    payload: JSON.stringify({contents:[{parts:[{text:prompt}]}], generationConfig:{responseMimeType:'application/json'}})
  });
  return JSON.parse(JSON.parse(res.getContentText()).candidates[0].content.parts[0].text);
}

function renderReport(enps, sent, topTopics, samples, ins) {
  const total = sent.pos + sent.neg + sent.neu || 1;
  const topicHtml = topTopics.map(([t,c]) => `<li><b>${t}</b> · ${c}건<br><span style="color:#666;font-size:.92em;">${(samples[t]||[]).join(' · ')}</span></li>`).join('');
  return `<div style="font-family:'Noto Sans KR',sans-serif;line-height:1.7;max-width:720px;color:#222;">
    <h2 style="border-bottom:2px solid #b45309;padding-bottom:.4rem;">분기 펄스서베이 — 경영진 요약</h2>
    <p style="color:#6a604f;">${new Date().toLocaleDateString('ko-KR')} 기준</p>

    <h3>정량 지표</h3>
    <ul>
      <li><b>ENPS</b>: ${enps}</li>
      <li><b>감성 분포</b>: 긍정 ${(sent.pos/total*100).toFixed(0)}% / 부정 ${(sent.neg/total*100).toFixed(0)}% / 중립 ${(sent.neu/total*100).toFixed(0)}%</li>
    </ul>

    <h3>상위 주제 (응답 빈도순)</h3>
    <ul>${topicHtml}</ul>

    <h3>📌 핵심 인사이트</h3>
    <p><b>가장 시급한 이슈 — </b>${ins.urgent}</p>
    <p><b>권고 액션</b></p>
    <ol>${ins.actions.map(a=>`<li>${a}</li>`).join('')}</ol>
    <p><b>강점 — </b>${ins.strength}</p>
    <p><b>다음 분기 측정 제안 — </b>${ins.next}</p>

    <p style="color:#999;font-size:.85em;margin-top:2rem;">자동 생성 · 응답은 익명이며 식별 정보는 AI에 전달되지 않았습니다.</p>
  </div>`;
}