// rakuten-product.jsx
// 楽天アフィリエイトJSONを受け取って成形・表示するためのユーティリティ
//
// 想定するJSON構造（バックエンド ↔ フロント）:
// {
//   "diagnosisId": "dx_abc123",
//   "products": [
//     {
//       "itemCode": "shop:item-id",          // 楽天の一意ID
//       "name": "商品名",
//       "shopName": "ショップ名",
//       "price": 4980,                        // 数値（整数円）
//       "imageUrl": "https://thumbnail.image.rakuten.co.jp/...",  // null許容
//       "imageUrls": ["url1", "url2"],        // optional, ギャラリー用
//       "affiliateUrl": "https://hb.afl.rakuten.co.jp/...",       // 必須
//       "genre": "gadget",                    // フォールバック分岐用
//       "hue": 250,                           // フォールバック背景の色相
//       "matchScore": 0.92,                   // 0-1
//       "matchReason": "「自分のための時間」スコア最上位とマッチ",
//       "matchedDesires": ["stimulation", "competence"]
//     }
//   ]
// }

// === 価格フォーマッタ ===
function formatPrice(price) {
  if (price == null) return "—";
  if (typeof price === "string") return price; // 既に整形済みなら通す
  const n = Number(price);
  if (Number.isNaN(n)) return "—";
  return "¥" + n.toLocaleString("ja-JP");
}

// === ジャンル → アイコン（SVG path）===
// 画像が無い時のフォールバック表示用
const GENRE_ICONS = {
  gadget: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <rect x="10" y="8" width="28" height="32" rx="4" />
      <line x1="10" y1="14" x2="38" y2="14" />
      <line x1="10" y1="34" x2="38" y2="34" />
      <circle cx="24" cy="37" r="0.8" fill="currentColor" />
    </svg>
  ),
  cosme: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <rect x="14" y="14" width="20" height="26" rx="2" />
      <path d="M18 14 V8 h12 v6" />
      <line x1="14" y1="22" x2="34" y2="22" />
    </svg>
  ),
  book: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M8 10 q8 -2 16 0 q8 -2 16 0 v28 q-8 -2 -16 0 q-8 -2 -16 0 z" />
      <line x1="24" y1="10" x2="24" y2="38" />
    </svg>
  ),
  home: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M8 22 L24 8 L40 22 V40 H8 Z" />
      <rect x="20" y="28" width="8" height="12" />
    </svg>
  ),
  food: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M10 26 q14 -8 28 0 q-2 12 -14 12 q-12 0 -14 -12 z" />
      <line x1="14" y1="20" x2="14" y2="14" />
      <line x1="20" y1="20" x2="20" y2="10" />
      <line x1="26" y1="20" x2="26" y2="12" />
    </svg>
  ),
  fashion: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M14 10 L18 14 L24 12 L30 14 L34 10 L40 18 L34 22 V40 H14 V22 L8 18 Z" />
    </svg>
  ),
  experience: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <circle cx="24" cy="24" r="14" />
      <path d="M24 14 v10 l7 4" />
    </svg>
  ),
  wellness: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <path d="M24 38 q-12 -6 -12 -16 a8 8 0 0 1 12 -6 a8 8 0 0 1 12 6 q0 10 -12 16 z" />
    </svg>
  ),
  fitness: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <line x1="6" y1="24" x2="42" y2="24" />
      <rect x="10" y="18" width="4" height="12" />
      <rect x="34" y="18" width="4" height="12" />
      <rect x="14" y="22" width="20" height="4" />
    </svg>
  ),
  default: (
    <svg viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="1.4">
      <rect x="10" y="14" width="28" height="22" rx="2" />
      <path d="M10 24 L20 18 L28 26 L34 22 L38 26" />
      <circle cx="32" cy="20" r="2" />
    </svg>
  ),
};

function getGenreIcon(genre) {
  return GENRE_ICONS[genre] || GENRE_ICONS.default;
}

// === ノーマライザ：バックエンドJSON → 内部表現 ===
// 楽天APIの生レスポンスでも、独自JSONでも、共通形に揃える
function normalizeProduct(raw) {
  // 楽天APIの itemDetails 形式と独自形式の両対応
  const item = raw.Item || raw.item || raw;
  return {
    itemCode: item.itemCode || item.id || `item_${Math.random().toString(36).slice(2, 8)}`,
    name: item.itemName || item.name || "—",
    shopName: item.shopName || "",
    price: typeof item.itemPrice === "number" ? item.itemPrice : (item.price ?? null),
    imageUrl: item.imageUrl
      || (item.mediumImageUrls && item.mediumImageUrls[0]?.imageUrl)
      || (item.smallImageUrls && item.smallImageUrls[0]?.imageUrl)
      || null,
    imageUrls: item.imageUrls
      || (item.mediumImageUrls && item.mediumImageUrls.map(o => o.imageUrl))
      || [],
    affiliateUrl: item.affiliateUrl || item.itemUrl || "#",
    genre: item.genre || "default",
    hue: typeof item.hue === "number" ? item.hue : 220,
    matchScore: typeof item.matchScore === "number" ? item.matchScore : null,
    matchReason: item.matchReason || item.why || "",
    matchedDesires: Array.isArray(item.matchedDesires) ? item.matchedDesires : [],
  };
}

function normalizeProductList(list) {
  if (!Array.isArray(list)) return [];
  return list.map(normalizeProduct);
}

// === 商品カードコンポーネント ===
// 雑誌風：大きな画像 + 価格大 + ショップ名 + マッチ理由 + 楽天ロゴ + PR
function RakutenProductCard({ product, rank, theme = "monochrome" }) {
  const p = product;
  const isTop = rank === 1;
  const fallbackHue = p.hue ?? 220;
  const matchPct = p.matchScore != null ? Math.round(p.matchScore * 100) : null;

  const hasLink = p.affiliateUrl && p.affiliateUrl !== "#";

  return (
    <a
      className={`rk-card ${isTop ? "is-top" : ""}`}
      href={hasLink ? p.affiliateUrl : undefined}
      target="_blank"
      rel="noopener noreferrer"
      style={{ "--hue": fallbackHue, textDecoration: "none", color: "inherit" }}
    >
      {/* 画像エリア */}
      <div className="rk-card-media">
        {p.imageUrl ? (
          <img
            src={p.imageUrl}
            alt={p.name}
            loading="lazy"
            onError={(e) => { e.currentTarget.style.display = "none"; }}
          />
        ) : (
          <div className="rk-card-fallback">
            <div className="rk-card-fallback-icon">
              {getGenreIcon(p.genre)}
            </div>
          </div>
        )}

        {/* PR / ランクバッジ */}
        <div className="rk-card-badges">
          {isTop && <span className="rk-badge rk-badge-top">TOP MATCH</span>}
          <span className="rk-badge rk-badge-pr">PR</span>
        </div>

        {/* マッチスコア */}
        {matchPct != null && (
          <div className="rk-card-match">
            <span className="rk-card-match-num">{matchPct}</span>
            <span className="rk-card-match-unit">%</span>
            <span className="rk-card-match-label">match</span>
          </div>
        )}
      </div>

      {/* 情報エリア */}
      <div className="rk-card-body">
        <div className="rk-card-rank">
          <span className="rk-card-rank-num">{String(rank).padStart(2, "0")}</span>
        </div>

        <h3 className="rk-card-name">{p.name}</h3>

        {p.shopName && <div className="rk-card-shop">{p.shopName}</div>}

        <div className="rk-card-price">
          <span className="rk-card-price-num">{formatPrice(p.price)}</span>
        </div>

        {p.matchReason && (
          <p className="rk-card-reason">{p.matchReason}</p>
        )}

        {/* 楽天ロゴ + 遷移ヒント */}
        <div className="rk-card-foot">
          <span className="rk-card-rakuten">
            <span className="rk-card-rakuten-mark" aria-hidden="true">R</span>
            <span className="rk-card-rakuten-text">楽天市場で見る</span>
          </span>
          <span className="rk-card-arrow" aria-hidden="true">→</span>
        </div>
      </div>
    </a>
  );
}

// グローバル公開
window.formatPrice = formatPrice;
window.getGenreIcon = getGenreIcon;
window.normalizeProduct = normalizeProduct;
window.normalizeProductList = normalizeProductList;
window.RakutenProductCard = RakutenProductCard;
