/* ============================================================================
 * Wildy — 프로필 게시물 3x3 그리드 (인스타 스타일)
 * ----------------------------------------------------------------------------
 *   spec: 본인 작성 게시물 그리드 + Wild 뱃지
 *
 *   사용:
 *     <window.WildyComponents.ProfilePostsGrid
 *        supabaseClient={...}
 *        userId={user.id}               // 누구의 프로필? (본인 또는 다른 사용자)
 *        lang="ko"
 *        onOpenPost={(index, posts) => ...}  // 클릭 시 detail 진입
 *     />
 *
 *   글로벌 노출:
 *     window.WildyComponents.ProfilePostsGrid
 *
 *   ⚠ 부모가 onOpenPost를 받아 PostDetailScreen에 posts 배열 그대로 전달해야
 *      이전/다음 네비가 같은 list에서 작동.
 * ========================================================================= */
(function (global) {
  'use strict';

  if (typeof React === 'undefined') {
    console.error('[profile-posts-grid.jsx] React not loaded');
    return;
  }
  const { useState, useEffect } = React;

  function withTimeout(promise, ms, fallback) {
    return Promise.race([
      promise,
      new Promise(resolve => setTimeout(() => resolve(fallback), ms)),
    ]);
  }

  function ProfilePostsGrid({ supabaseClient, userId, lang = 'ko', onOpenPost, filter = 'all', refreshKey = 0, editable = false, onCreateClick }) {
    const [posts, setPosts] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState('');
    const showEmpty = () => {
      setPosts([]);
      setError('');
      setLoading(false);
    };

    useEffect(() => {
      if (!supabaseClient || !userId) { setPosts([]); setLoading(false); return; }
      let active = true;
      setLoading(true);
      setError('');
      (async () => {
        // 'sparkled' 필터 — 본인이 ✦ 준 게시물 (stars 테이블 → posts JOIN)
        if (filter === 'sparkled') {
          try {
            const { data: starRows, error: starErr } = await withTimeout(
              supabaseClient
                .from('stars')
                .select('target_id,created_at,posts:posts!target_id(id,text,image_urls,video_url,star_count,comment_count,created_at,game_tag,author_id,is_deleted)')
                .eq('user_id', userId)
                .eq('target_type', 'post')
                .order('created_at', { ascending: false })
                .limit(60),
              7000,
              { data: [], error: null }
            );
            if (!active) return;
            if (starErr) throw starErr;
            const list = (starRows || []).map(r => r.posts).filter(p => p && !p.is_deleted);
            setPosts(list);
            setLoading(false);
          } catch (e) {
            if (!active) return;
            console.error('[ProfilePostsGrid] sparkled load failed', e);
            showEmpty();
          }
          return;
        }

        // 'tagged' 필터는 post_tags 테이블에서 fetch — 별도 흐름
        if (filter === 'tagged') {
          try {
            const { data: tagRows, error: tagErr } = await withTimeout(
              supabaseClient
                .from('post_tags')
                .select('post_id,visibility,approved,posts:posts!post_id(id,text,image_urls,video_url,star_count,comment_count,created_at,game_tag,author_id,is_deleted)')
                .eq('tagged_user_id', userId)
                .eq('approved', true)
                .order('created_at', { ascending: false })
                .limit(60),
              7000,
              { data: [], error: null }
            );
            if (!active) return;
            if (tagErr) throw tagErr;
            const list = (tagRows || []).map(t => t.posts).filter(p => p && !p.is_deleted);
            setPosts(list);
            setLoading(false);
          } catch (e) {
            if (!active) return;
            console.error('[ProfilePostsGrid] tagged load failed', e);
            showEmpty();
          }
          return;
        }

        // 일반 필터 (all/starred/media)
        // game_tag는 FK가 아니라서 posts -> wilds embed 조인을 먼저 시도하면
        // PostgREST가 관계 탐색에 실패하거나 timeout 후 fallback되어 프로필이 늦게 뜬다.
        // 프로필 첫 화면은 게시글 원본만 빠르게 가져오고 Wild 라벨은 game_tag로 표시한다.
        let data, err;
        try {
          const r = await withTimeout(
            supabaseClient
              .from('posts')
              .select('id,text,image_urls,video_url,star_count,comment_count,created_at,game_tag,author_id')
              .eq('author_id', userId)
              .eq('is_deleted', false)
              .order('created_at', { ascending: false })
              .limit(60),
            2500,
            { data: [], error: null }
          );
          data = r.data; err = r.error;
        } catch (e) { err = e; }

        if (!active) return;
        if (err) {
          console.error('[ProfilePostsGrid] load failed', err);
          showEmpty();
          return;
        }
        setPosts(data || []);
        setLoading(false);
      })();
      return () => { active = false; };
    }, [supabaseClient, userId, filter, refreshKey]);

    const wildLabel = (w) => {
      if (!w) return null;
      if (lang === 'en' && w.title_en) return w.title_en;
      if (lang === 'ja' && w.title_ja) return w.title_ja;
      if (lang === 'zh' && w.title_zh) return w.title_zh;
      if (lang === 'id' && w.title_id) return w.title_id;
      return w.short_name || w.name;
    };

    // 필터 적용 — 'tagged' / 'sparkled'는 위에서 별도 fetch함 (이미 filtered)
    const filtered = (() => {
      if (filter === 'tagged' || filter === 'sparkled') return posts;
      if (filter === 'starred') return posts.filter(p => (p.star_count || 0) >= 100);
      if (filter === 'media') {
        return posts.filter(p => p.video_url || (Array.isArray(p.image_urls) && p.image_urls.length > 0));
      }
      return posts;
    })();

    if (loading) {
      return (
        <div className="grid grid-cols-3 gap-1">
          {Array.from({ length: 9 }).map((_, i) => (
            <div key={i} className="aspect-square animate-pulse bg-slate-100">
              <div className="h-full w-full bg-gradient-to-br from-slate-100 via-sky-50 to-white"></div>
            </div>
          ))}
        </div>
      );
    }
    if (error) {
      return <div className="my-3 rounded-2xl bg-rose-50 px-4 py-3 text-sm text-rose-600 mx-4">{error}</div>;
    }
    // 빈 상태 — 인스타 패턴 (그리드 첫 칸 + 제거, 빈 상태에만 큰 CTA)
    if (filtered.length === 0) {
      const cfg = filter === 'starred'  ? { icon: '✦', title: '아직 받은 Sparkle이 없어요', cta: null }
                : filter === 'sparkled' ? { icon: '✦', title: '아직 Sparkle한 게시물이 없어요', cta: null }
                : filter === 'media'    ? { icon: '🎬', title: '아직 미디어가 없어요',     cta: '+ 미디어 올리기' }
                : filter === 'tagged'   ? { icon: '🏷️', title: '아직 태그된 게시물이 없어요', cta: null }
                : /* all */               { icon: '📷', title: '아직 게시물이 없어요',     cta: '+ 첫 게시물 작성하기' };
      const showCta = editable && cfg.cta && onCreateClick;
      return (
        <div className="py-16 text-center px-6" style={{ wordBreak: 'keep-all' }}>
          <div className="text-6xl mb-4">{cfg.icon}</div>
          <p className="font-display text-base font-bold text-wildy-ink mb-2">{cfg.title}</p>
          {showCta && (
            <button
              onClick={onCreateClick}
              className="mt-5 rounded-full bg-wildy-ink px-6 py-3 text-sm font-bold text-white hover:-translate-y-0.5 transition shadow-ink"
            >
              {cfg.cta}
            </button>
          )}
        </div>
      );
    }

    // posts에서 검색 시 wild 정보가 없으면 indexing을 위해 원본 posts 그대로 전달.
    // filter된 list 안의 index로 PostDetailScreen prev/next 작동.
    return (
      <div className="grid grid-cols-3 gap-1">
        {filtered.map((p, i) => {
          const w = p.wild || p.wilds;  // alias 또는 plain fallback
          const firstImage = Array.isArray(p.image_urls) && p.image_urls.length > 0 ? p.image_urls[0] : null;
          const badge = wildLabel(w) || (p.game_tag ? p.game_tag.toUpperCase().slice(0, 6) : null);
          return (
            <button
              key={p.id}
              onClick={() => onOpenPost && onOpenPost(i, filtered)}
              className="relative aspect-square bg-slate-100 overflow-hidden group"
            >
              {firstImage ? (
                <img
                  src={firstImage}
                  alt=""
                  className="h-full w-full object-cover transition group-hover:scale-105"
                  loading="lazy"
                  onError={(e) => { e.target.style.display = 'none'; }}
                />
              ) : (
                <div className="absolute inset-0 flex items-center justify-center bg-gradient-to-br from-sky-50 to-white p-3 text-[10px] leading-tight text-slate-600 text-center" style={{ wordBreak: 'keep-all' }}>
                  <span className="line-clamp-5">{(p.text || '').slice(0, 80) || '(텍스트 없음)'}</span>
                </div>
              )}

              {/* Wild 뱃지 */}
              {badge && (
                <span className="absolute top-1 left-1 rounded bg-black/60 backdrop-blur px-1.5 py-0.5 text-[9px] font-black text-white">
                  {w?.emoji ? `${w.emoji} ` : ''}{badge}
                </span>
              )}

              {/* 이미지 여러 장 표시 */}
              {Array.isArray(p.image_urls) && p.image_urls.length > 1 && (
                <span className="absolute top-1 right-1 rounded bg-black/60 backdrop-blur px-1 py-0.5 text-[9px] font-bold text-white">⊞</span>
              )}

              {/* 동영상 표시 */}
              {p.video_url && (
                <span className="absolute bottom-1 right-1 rounded bg-black/70 backdrop-blur px-1.5 py-0.5 text-[10px] font-bold text-white">▶</span>
              )}

              {/* 하단 stats — hover */}
              <div className="absolute inset-0 flex items-end justify-center gap-3 bg-black/40 text-white text-xs font-bold opacity-0 group-hover:opacity-100 transition pb-2">
                <span>✦ {p.star_count || 0}</span>
                <span>💬 {p.comment_count || 0}</span>
              </div>
            </button>
          );
        })}
      </div>
    );
  }

  global.WildyComponents = global.WildyComponents || {};
  global.WildyComponents.ProfilePostsGrid = ProfilePostsGrid;
})(typeof window !== 'undefined' ? window : globalThis);
