/* ============================================================================
 * 서명전에 — TDS BarChart 컴포넌트  (Task #160)
 *
 *  · TDS Mobile 2026-03 BarChart 스펙. 데이터 값을 막대 높이로 시각화.
 *    색상 테마로 특정 막대/전체/우측 N 개를 강조할 수 있어요.
 *
 *  · props:
 *      data*     BarChartData[] — value / maxValue / label / theme / barAnnotation
 *      fill*     AllBar | SingleBar | Auto — 3 타입 중 하나 (type 필드로 구분)
 *      height    number(px, 기본 205) — 차트 전체 세로 길이 (막대 개수 무관)
 *      className / style — 패스스루
 *
 *  · data item (BarChartData):
 *      value*         number — 실제 값 (막대 높이 = value/maxValue 비례)
 *      maxValue       number — 생략 시 data 내 최대 value 자동 사용
 *      label          string — X축 레이블
 *      theme          7 테마 — 항목별 지정이 있으면 fill 과 병합 시 우선
 *      barAnnotation  string|number — 막대 위에 표시할 텍스트/숫자
 *
 *  · fill 3 타입:
 *      { type: "all-bar",    theme }                  — 모든 막대 같은 색
 *      { type: "single-bar", theme, barIndex }        — 특정 인덱스 1개만
 *      { type: "auto",       count }                  — 오른쪽부터 count 개,
 *                                                       blue → green → yellow → orange → red → grey 순
 *
 *  · 7 테마: blue / green / yellow / orange / red / grey / default
 *    default = 회색 중립 (적극 강조 아님). 미지정 = default.
 *
 *  · data.length > 12 시 첫 번째와 마지막 항목만 label + barAnnotation 을
 *    표시해요 (텍스트 겹침 방지). 중간 막대는 색만 보여요.
 *
 *  · 모든 색/폰트/간격은 var(--tds-…) 토큰. 하드코딩 없음.
 *  · prefers-reduced-motion 시 막대 transition OFF.
 *
 *  · role="img" + aria-label 자동 (데이터 요약) — 스크린 리더 대응.
 * ========================================================================== */

// ─── 상수 ─────────────────────────────────────────────────────────────
const __BCHART_THEMES = ["blue", "green", "yellow", "orange", "red", "grey", "default"];
// auto 타입 오른쪽부터 적용 순서 (스펙 고정).
const __BCHART_AUTO_ORDER = ["blue", "green", "yellow", "orange", "red", "grey"];
const __BCHART_LABEL_CAP = 12; // data 길이가 이 값을 초과하면 첫/마지막만 표시.

function __bchartWarn(msg) {
  if (typeof console !== "undefined" && console.warn) console.warn("[BarChart] " + msg);
}

function __bchartTheme(raw) {
  if (raw == null) return "default";
  if (__BCHART_THEMES.indexOf(raw) === -1) {
    __bchartWarn('theme "' + raw + '" 은 지원하지 않아요. 가능한 값: ' + __BCHART_THEMES.join(", ") + ". \"default\" 로 폴백.");
    return "default";
  }
  return raw;
}

// ─── fill 결정 로직 ─────────────────────────────────────────────────
// 각 막대(index 기준)의 최종 테마를 계산.
// 항목 개별 theme > fill 타입별 테마 > "default"
function __bchartResolveThemes(data, fill) {
  const n = data.length;
  const out = new Array(n).fill("default");

  if (!fill || typeof fill !== "object") {
    // fill 미지정 — data 자체의 theme 만 사용, 나머지는 default.
    for (let i = 0; i < n; i++) {
      out[i] = __bchartTheme(data[i] && data[i].theme);
    }
    return out;
  }

  const type = fill.type;

  if (type === "all-bar") {
    const t = __bchartTheme(fill.theme);
    for (let i = 0; i < n; i++) {
      // 항목별 theme 가 명시되어 있으면 그걸 우선.
      out[i] = data[i] && data[i].theme ? __bchartTheme(data[i].theme) : t;
    }
    return out;
  }

  if (type === "single-bar") {
    const t = __bchartTheme(fill.theme);
    let idx = fill.barIndex;
    if (typeof idx !== "number" || !isFinite(idx)) {
      __bchartWarn("single-bar 의 barIndex 는 number 여야 해요. 0 으로 폴백.");
      idx = 0;
    }
    idx = Math.floor(idx);
    if (idx < 0 || idx >= n) {
      __bchartWarn("barIndex=" + idx + " 는 data 범위(0~" + (n - 1) + ") 밖이에요.");
    }
    for (let i = 0; i < n; i++) {
      if (data[i] && data[i].theme) out[i] = __bchartTheme(data[i].theme);
      else if (i === idx) out[i] = t;
      else out[i] = "default";
    }
    return out;
  }

  if (type === "auto") {
    let count = fill.count;
    if (typeof count !== "number" || !isFinite(count)) {
      __bchartWarn("auto 의 count 는 number 여야 해요. data.length 로 폴백.");
      count = n;
    }
    count = Math.max(0, Math.min(n, Math.floor(count)));
    // 오른쪽에서 count 개 — 가장 오른쪽이 blue, 왼쪽으로 가며 auto 순서.
    // count 가 6 초과면 6번째 이후 (더 왼쪽) 는 마지막 색(grey) 반복 — 보수적 해석.
    for (let i = 0; i < n; i++) {
      if (data[i] && data[i].theme) {
        out[i] = __bchartTheme(data[i].theme);
        continue;
      }
      const distFromRight = n - 1 - i; // 0 이 가장 오른쪽
      if (distFromRight >= count) {
        out[i] = "default";
      } else {
        const orderIdx = distFromRight < __BCHART_AUTO_ORDER.length
          ? distFromRight
          : __BCHART_AUTO_ORDER.length - 1; // grey 에 고정
        out[i] = __BCHART_AUTO_ORDER[orderIdx];
      }
    }
    return out;
  }

  __bchartWarn('fill.type "' + type + '" 은 지원하지 않아요. "all-bar"/"single-bar"/"auto" 중 하나여야 해요.');
  // 알 수 없는 타입 — data 자체의 theme 만 사용.
  for (let i = 0; i < n; i++) {
    out[i] = __bchartTheme(data[i] && data[i].theme);
  }
  return out;
}

// ─── maxValue 결정 ────────────────────────────────────────────────
// 항목마다 maxValue 가 다를 수 있지만, 차트 전체 높이 정규화를 위해
// max 값을 각 막대별 개별 처리 (스펙 상 "value/maxValue 비율").
// 항목의 maxValue 생략 시 data 전체 최대 value 로 폴백.
function __bchartResolveMax(data) {
  let globalMax = 0;
  for (let i = 0; i < data.length; i++) {
    const v = data[i] && typeof data[i].value === "number" ? data[i].value : 0;
    if (v > globalMax) globalMax = v;
  }
  if (globalMax === 0) globalMax = 1; // 0 분모 방지
  return globalMax;
}

function __bchartRatio(value, maxV) {
  if (typeof value !== "number" || !isFinite(value)) return 0;
  if (typeof maxV !== "number" || !isFinite(maxV) || maxV <= 0) return 0;
  const r = value / maxV;
  if (r < 0) return 0;
  if (r > 1) return 1;
  return r;
}

// ─── BarChart 본체 ───────────────────────────────────────────────
function BarChart({
  data,
  fill,
  height = 205,
  className = "",
  style,
  ...rest
}) {
  if (!Array.isArray(data) || data.length === 0) {
    __bchartWarn("data 는 길이 > 0 인 배열이어야 해요.");
    return null;
  }

  const safeHeight = typeof height === "number" && isFinite(height) && height > 0 ? height : 205;
  const themes = __bchartResolveThemes(data, fill);
  const globalMax = __bchartResolveMax(data);

  // 데이터가 많으면 첫/마지막만 label + annotation 노출.
  const manyData = data.length > __BCHART_LABEL_CAP;

  // 접근성: "1월 6, 2월 5, …" 같은 요약 라벨.
  const aria = data
    .map((d) => (d && d.label ? d.label + " " : "") + (d && d.value != null ? d.value : ""))
    .join(", ");

  const mergedStyle = Object.assign(
    { "--tds-bchart-h": safeHeight + "px" },
    style || {}
  );

  const cls = ["tds-bchart", manyData && "tds-bchart--many", className]
    .filter(Boolean)
    .join(" ");

  return (
    <div
      className={cls}
      style={mergedStyle}
      role="img"
      aria-label={"막대 그래프 — " + aria}
      {...rest}
    >
      <div className="tds-bchart__bars" aria-hidden="true">
        {data.map((d, i) => {
          const theme = themes[i] || "default";
          const maxV = typeof d.maxValue === "number" && d.maxValue > 0 ? d.maxValue : globalMax;
          const ratio = __bchartRatio(d && d.value, maxV);
          const showEdgeOnly = manyData && i !== 0 && i !== data.length - 1;
          const barStyle = { "--tds-bchart-ratio": ratio };

          return (
            <div
              key={i}
              className={"tds-bchart__col tds-bchart__col--" + theme + (showEdgeOnly ? " tds-bchart__col--hide-meta" : "")}
            >
              {/* 상단 어노테이션 */}
              <div className="tds-bchart__annotation">
                {d && d.barAnnotation != null ? d.barAnnotation : ""}
              </div>
              {/* 막대 트랙(전체) + 실제 채워진 막대(높이 = ratio) */}
              <div className="tds-bchart__track">
                <div className="tds-bchart__bar" style={barStyle} />
              </div>
              {/* 하단 라벨 */}
              <div className="tds-bchart__label">
                {d && d.label != null ? d.label : ""}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─── 글로벌 등록 ─────────────────────────────────────────────────
window.BarChart = BarChart;
Object.assign(window, { BarChart });
