/* ============================================================================
 * Wildy — Real Chat Screen (Supabase 백엔드 연결)
 * ----------------------------------------------------------------------------
 *   spec: Part C — 채팅 시스템 (베타 핵심)
 *
 *   기능:
 *     - chat_rooms + messages 실제 연결
 *     - Supabase Realtime 구독 (postgres_changes)
 *     - 메시지별 [번역] 버튼 (/api/translate)
 *     - 본인 메시지 Soft Delete (is_deleted=true)
 *     - 자동 스크롤
 *     - 차단된 사용자 메시지 자동 필터 (RLS)
 *
 *   사용:
 *     <window.WildyComponents.RealChatScreen
 *        supabaseClient={...}
 *        user={authedUser}
 *        roomId={roomId}
 *        roomName={'LoL 메인'}
 *        roomEmoji={'🎮'}
 *        roomType={'group'}      // 'group' | 'direct'
 *        myLang={'ko'}
 *        onBack={() => ...}
 *     />
 *
 *   글로벌 노출:
 *     window.WildyComponents.RealChatScreen
 * ========================================================================= */
(function (global) {
  'use strict';

  if (typeof React === 'undefined') {
    console.error('[real-chat-screen.jsx] React not loaded');
    return;
  }
  const { useState, useEffect, useRef, useCallback } = React;

  // 시간 포맷 (HH:MM)
  function timeOf(ts) {
    try {
      const d = new Date(ts);
      return d.toTimeString().slice(0, 5);
    } catch {
      return '';
    }
  }

  // 날짜 분리 헤더용 (YYYY-MM-DD)
  function dateOf(ts) {
    try {
      return new Date(ts).toISOString().slice(0, 10);
    } catch {
      return '';
    }
  }

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

  function RealChatScreen({
    supabaseClient,
    user,
    roomId,
    roomName,
    roomEmoji = '💬',
    roomType = 'group',
    myLang = 'ko',
    onBack,
  }) {
    const [messages, setMessages] = useState([]);
    const [loading, setLoading] = useState(true);
    const [loadError, setLoadError] = useState('');
    const [sending, setSending] = useState(false);
    const [text, setText] = useState('');
    const [translations, setTranslations] = useState({});  // { msgId: { text, lang } | 'loading' | 'error' }
    const [showOrigOnly, setShowOrigOnly] = useState({});   // { msgId: true } = 번역 숨기고 원문만
    const [uploading, setUploading] = useState(false);
    const scrollRef = useRef(null);
    const channelRef = useRef(null);
    const fileInputRef = useRef(null);
    const helpers = (global.WildyLib && global.WildyLib.SupabaseHelpers) || {};

    // ─── 메시지 로드 ─────────────────────────────────────────────────
    useEffect(() => {
      if (!supabaseClient || !roomId) { setLoading(false); return; }
      let active = true;
      setLoading(true);
      setLoadError('');
      (async () => {
        try {
          const { data, error } = await withTimeout(supabaseClient
            .from('messages')
            .select('id,room_id,sender_id,type,text,image_url,language,reply_to,is_pinned,is_deleted,status,created_at,sender:users!sender_id(id,username,display_name,avatar,preferred_language)')
            .eq('room_id', roomId)
            .order('created_at', { ascending: true })
            .limit(100), 7000, { data: [], error: new Error('messages_timeout') });
          if (!active) return;
          if (error) {
            // 임베드 실패 시 plain fallback
            console.warn('[RealChatScreen] join failed, fallback', error.message);
            const r2 = await withTimeout(supabaseClient
              .from('messages')
              .select('id,room_id,sender_id,type,text,image_url,language,reply_to,is_pinned,is_deleted,status,created_at')
              .eq('room_id', roomId)
              .order('created_at', { ascending: true })
              .limit(100), 7000, { data: [], error: new Error('messages_fallback_timeout') });
            if (!active) return;
            if (r2.error) throw r2.error;
            setMessages(r2.data || []);
          } else {
            setMessages(data || []);
          }
        } catch (e) {
          if (!active) return;
          console.error('[RealChatScreen] load failed', e);
          setLoadError(helpers.translateAuthError ? helpers.translateAuthError(e) : (e?.message || '메시지를 불러오지 못했어요'));
        } finally {
          if (active) setLoading(false);
        }
      })();
      return () => { active = false; };
    }, [supabaseClient, roomId]);

    // ─── Realtime 구독 ──────────────────────────────────────────────
    useEffect(() => {
      if (!supabaseClient || !roomId) return;
      const channel = supabaseClient
        .channel(`real-chat:${roomId}`)
        .on('postgres_changes', {
          event: 'INSERT',
          schema: 'public',
          table: 'messages',
          filter: `room_id=eq.${roomId}`,
        }, (payload) => {
          const m = payload?.new;
          if (!m) return;
          setMessages(prev => {
            if (prev.some(p => p.id === m.id)) return prev;
            return [...prev, m];
          });
        })
        .on('postgres_changes', {
          event: 'UPDATE',
          schema: 'public',
          table: 'messages',
          filter: `room_id=eq.${roomId}`,
        }, (payload) => {
          const m = payload?.new;
          if (!m) return;
          setMessages(prev => prev.map(p => p.id === m.id ? { ...p, ...m } : p));
        })
        .subscribe();
      channelRef.current = channel;
      return () => {
        try { supabaseClient.removeChannel(channel); } catch {}
        channelRef.current = null;
      };
    }, [supabaseClient, roomId]);

    // ─── 자동 스크롤 ─────────────────────────────────────────────────
    useEffect(() => {
      const el = scrollRef.current;
      if (el) el.scrollTop = el.scrollHeight;
    }, [messages.length]);

    // ─── 메시지 전송 ─────────────────────────────────────────────────
    const send = useCallback(async () => {
      const v = (text || '').trim();
      if (!v || sending || !supabaseClient || !user?.id) return;
      setSending(true);
      try {
        // 1) AI 모더레이션 사전 검증 (이중 안전: 한국어 키워드 + OpenAI)
        try {
          const modHeaders = { 'Content-Type': 'application/json' };
          if (supabaseClient) {
            try {
              const { data } = await supabaseClient.auth.getSession();
              const token = data?.session?.access_token;
              if (token) modHeaders.Authorization = `Bearer ${token}`;
            } catch {}
          }
          const mr = await fetch('/api/moderate', {
            method: 'POST',
            headers: modHeaders,
            body: JSON.stringify({
              text: v.slice(0, 2000),
              context_type: 'chat_message',
              context_room_id: roomId,
            }),
          });
          if (mr.ok) {
            const md = await mr.json();
            if (md && md.ok === false && md.flagged) {
              alert(md.reason || '부적절한 표현이 포함되어 있어요. 다시 작성해주세요.');
              setSending(false);
              return;
            }
          }
        } catch (modErr) {
          // 모더레이션 호출 실패 = 통과 (사용자 메시지 차단 X)
          console.warn('[RealChatScreen] moderation skipped', modErr);
        }

        // 2) 메시지 INSERT
        const { error } = await supabaseClient
          .from('messages')
          .insert({
            room_id: roomId,
            sender_id: user.id,
            type: 'text',
            text: v.slice(0, 4000),
            language: myLang,
          });
        if (error) throw error;
        setText('');
        // Realtime이 자동으로 추가하지만, optimistic 추가는 skip (실시간 ms 단위)
      } catch (e) {
        console.error('[RealChatScreen] send failed', e);
        alert(helpers.translateAuthError ? helpers.translateAuthError(e) : (e?.message || '전송 실패'));
      } finally {
        setSending(false);
      }
    }, [text, sending, supabaseClient, user?.id, roomId, myLang, helpers]);

    // ─── 이미지 업로드 + 이미지 메시지 전송 ────────────────────────────
    const uploadImage = useCallback(async (file) => {
      if (!supabaseClient || !user?.id || !file) return;
      if (file.size > 5 * 1024 * 1024) {
        alert('이미지는 5MB 이하만 업로드 가능해요');
        return;
      }
      if (!file.type.startsWith('image/')) {
        alert('이미지 파일만 업로드 가능해요');
        return;
      }
      setUploading(true);
      try {
        const ext = (file.name || 'img').split('.').pop()?.toLowerCase() || 'png';
        const safeExt = ['png', 'jpg', 'jpeg', 'webp', 'gif'].includes(ext) ? ext : 'png';
        const ts = Date.now();
        const rand = Math.random().toString(36).slice(2, 8);
        const path = `${user.id}/chat/${roomId}/${ts}-${rand}.${safeExt}`;

        const { error: uploadErr } = await supabaseClient.storage
          .from('post-images')
          .upload(path, file, { cacheControl: '3600', upsert: false, contentType: file.type });
        if (uploadErr) throw uploadErr;

        const { data: pub } = supabaseClient.storage.from('post-images').getPublicUrl(path);
        const imageUrl = pub?.publicUrl;
        if (!imageUrl) throw new Error('이미지 URL 생성 실패');

        const { error: insErr } = await supabaseClient
          .from('messages')
          .insert({
            room_id: roomId,
            sender_id: user.id,
            type: 'image',
            image_url: imageUrl,
            text: '[이미지]',  // type='text' 아니지만 fallback 검색용
            language: myLang,
          });
        if (insErr) throw insErr;
      } catch (e) {
        console.error('[RealChatScreen] uploadImage failed', e);
        alert(helpers.translateAuthError ? helpers.translateAuthError(e) : (e?.message || '이미지 전송 실패'));
      } finally {
        setUploading(false);
        if (fileInputRef.current) fileInputRef.current.value = '';
      }
    }, [supabaseClient, user?.id, roomId, myLang, helpers]);

    const onFileChange = (e) => {
      const file = e.target.files?.[0];
      if (file) uploadImage(file);
    };

    // ─── 본인 메시지 삭제 (soft) ───────────────────────────────────────
    const deleteOwn = useCallback(async (msgId) => {
      if (!supabaseClient) return;
      if (!confirm('이 메시지를 삭제할까요? 90일간 운영진 조회만 가능해요.')) return;
      try {
        const { error } = await supabaseClient
          .from('messages')
          .update({ is_deleted: true })
          .eq('id', msgId)
          .eq('sender_id', user.id);
        if (error) throw error;
        setMessages(prev => prev.map(m => m.id === msgId ? { ...m, is_deleted: true } : m));
      } catch (e) {
        console.error('[RealChatScreen] delete failed', e);
        alert(helpers.translateAuthError ? helpers.translateAuthError(e) : '삭제 실패');
      }
    }, [supabaseClient, user?.id, helpers]);

    // ─── 번역 토글 ─────────────────────────────────────────────────
    const translate = useCallback(async (msg) => {
      if (!msg?.text || msg.is_deleted) return;
      // 이미 번역이 있으면 토글
      if (translations[msg.id] && typeof translations[msg.id] === 'object') {
        setShowOrigOnly(prev => ({ ...prev, [msg.id]: !prev[msg.id] }));
        return;
      }
      setTranslations(prev => ({ ...prev, [msg.id]: 'loading' }));
      try {
        // 사용자별 일일 한도 카운트를 위해 access token 첨부
        const headers = { 'Content-Type': 'application/json' };
        if (supabaseClient) {
          try {
            const { data } = await supabaseClient.auth.getSession();
            const token = data?.session?.access_token;
            if (token) headers.Authorization = `Bearer ${token}`;
          } catch {}
        }
        const r = await fetch('/api/translate', {
          method: 'POST',
          headers,
          body: JSON.stringify({
            text: msg.text,
            source_lang: msg.language || undefined,
            target_lang: myLang,
          }),
        });
        const data = await r.json();
        if (!r.ok || !data.ok) {
          throw new Error(data?.message || '번역 실패');
        }
        setTranslations(prev => ({
          ...prev,
          [msg.id]: {
            text: data.translated_text,
            lang: data.target_lang,
            fromCache: data.from_cache,
            failed: data.failed || false,
            logId: data.translation_log_id || null,   // 👍/👎 피드백 연결용
          },
        }));
      } catch (e) {
        console.warn('[RealChatScreen] translate failed', e);
        setTranslations(prev => ({ ...prev, [msg.id]: 'error' }));
      }
    }, [translations, myLang, supabaseClient]);

    // ─── 번역 만족도 피드백 (Phase 1-E3) ─────────────────────────────
    //   translation_feedback 테이블에 직접 INSERT (RLS: authenticated 만 + WITH CHECK true)
    //   logId 없으면 (캐시/skip/익명) 피드백 비활성.
    const [feedbacks, setFeedbacks] = useState({});  // { msgId: 1 | -1 } — 클릭 후 토글 잠금
    const sendFeedback = useCallback(async (msgId, logId, value) => {
      if (!supabaseClient || !logId || !user?.id) return;
      if (feedbacks[msgId]) return;   // 중복 클릭 방지
      setFeedbacks(prev => ({ ...prev, [msgId]: value }));
      try {
        const { error } = await supabaseClient.from('translation_feedback').insert({
          translation_log_id: logId,
          feedback: value,
        });
        if (error) throw error;
        console.info('[RealChatScreen] feedback sent', { msgId, value });
      } catch (e) {
        console.warn('[RealChatScreen] feedback failed', e?.message || e);
        // 실패 시 롤백
        setFeedbacks(prev => { const next = { ...prev }; delete next[msgId]; return next; });
      }
    }, [supabaseClient, user?.id, feedbacks]);

    // ─── 렌더 ───────────────────────────────────────────────────────
    const renderMessage = (m, prevMsg) => {
      const isMine = m.sender_id === user?.id;
      const senderName = m.sender?.display_name || m.sender?.username || (isMine ? '나' : 'Wilder');
      const avatarObj = m.sender?.avatar;
      const senderAvatarUrl = avatarObj && typeof avatarObj === 'object' && avatarObj.type === 'image' ? avatarObj.url : null;
      const showDateHeader = !prevMsg || dateOf(prevMsg.created_at) !== dateOf(m.created_at);
      const tr = translations[m.id];
      const hideOrig = false;
      const showTranslation = tr && typeof tr === 'object' && !showOrigOnly[m.id];

      return (
        <React.Fragment key={m.id}>
          {showDateHeader && (
            <div className="my-3 flex items-center justify-center">
              <span className="rounded-full bg-slate-100 px-3 py-1 text-[11px] font-bold text-slate-500">
                {new Date(m.created_at).toLocaleDateString('ko-KR', { month: 'long', day: 'numeric', weekday: 'short' })}
              </span>
            </div>
          )}
          <div className={`flex gap-2 mb-3 ${isMine ? 'flex-row-reverse' : ''}`}>
            {!isMine && (
              <div className="w-8 h-8 rounded-full bg-slate-200 flex-shrink-0 flex items-center justify-center text-sm overflow-hidden">
                {senderAvatarUrl
                  ? <img src={senderAvatarUrl} alt="" className="w-full h-full object-cover" onError={(e) => { e.target.style.display = 'none'; }} />
                  : (senderName?.[0] || '?').toUpperCase()}
              </div>
            )}
            <div className={`flex-1 min-w-0 ${isMine ? 'flex flex-col items-end' : ''}`}>
              {!isMine && (
                <div className="text-[11px] font-bold text-slate-600 mb-0.5 flex items-center gap-1.5">
                  <span>{senderName}</span>
                  {/* 언어 칩 — 다른 언어 메시지일 때만 표시, 클릭 시 번역 */}
                  {m.type === 'text' && m.text && m.language && m.language !== myLang && (
                    <button
                      onClick={() => translate(m)}
                      disabled={tr === 'loading'}
                      className={`rounded-full px-1.5 py-0.5 text-[9px] font-black uppercase tracking-wider transition border ${
                        tr === 'loading'
                          ? 'bg-slate-100 text-slate-400 border-slate-200 cursor-wait'
                          : tr === 'error'
                          ? 'bg-rose-50 text-rose-600 border-rose-200 hover:bg-rose-100'
                          : (tr && !showOrigOnly[m.id])
                          ? 'bg-amber-100 text-amber-700 border-amber-200 hover:bg-amber-50'
                          : 'bg-sky-50 text-sky-600 border-sky-200 hover:bg-sky-100'
                      }`}
                      title={
                        tr === 'loading' ? '번역 중...'
                        : tr === 'error' ? '번역 실패 — 재시도'
                        : (tr && !showOrigOnly[m.id]) ? '✦ 번역됨 — 클릭하면 원문 보기'
                        : `${(m.language || '').toUpperCase()} → ${(myLang || '').toUpperCase()} 번역하기`
                      }
                    >
                      {tr === 'loading' ? '...' : (m.language || '').toUpperCase()}
                      {tr && typeof tr === 'object' && !showOrigOnly[m.id] && ' ✓'}
                    </button>
                  )}
                </div>
              )}
              {m.is_deleted ? (
                <div className="inline-block max-w-[80%] rounded-2xl bg-slate-100 px-3 py-2 text-xs text-slate-400 italic">
                  🚫 삭제된 메시지
                </div>
              ) : (
                <div className="group inline-flex flex-col gap-1 max-w-[80%]">
                  {m.type === 'image' && m.image_url ? (
                    <a href={m.image_url} target="_blank" rel="noopener" className="block rounded-2xl overflow-hidden border border-slate-200">
                      <img
                        src={m.image_url}
                        alt=""
                        className="max-w-[280px] max-h-[280px] object-cover"
                        loading="lazy"
                        onError={(e) => { e.target.style.display = 'none'; }}
                      />
                    </a>
                  ) : (
                    <div className={`inline-block rounded-2xl px-3 py-2 text-sm whitespace-pre-wrap break-words ${isMine ? 'bg-sky-500 text-white' : 'bg-slate-100 text-slate-800'}`}>
                      {m.text}
                    </div>
                  )}
                  {showTranslation && m.type === 'text' && (() => {
                    // Phase 1-A2 silent-wrong 완화 — 짧은 입력은 gpt-4o 도
                    //   few-shot echo / 의역 회귀 위험. 사용자가 의심하도록 경고.
                    //   기준: 원문·번역 둘 다 12자 이하 (실측 #2/#8 회귀 범위)
                    const SHORT_LEN = 12;
                    const isShortRisky = !tr.failed &&
                      (m.text || '').trim().length <= SHORT_LEN &&
                      (tr.text || '').trim().length <= SHORT_LEN;
                    return (
                    <>
                      {/* 짧은 입력 silent-wrong 경고 (gpt-4o 도 짧은 캐주얼은 가끔 빗나감) */}
                      {isShortRisky && (
                        <div className="inline-flex items-center gap-1 rounded-full bg-amber-100 border border-amber-300 px-2 py-0.5 text-[10px] font-bold text-amber-800">
                          🔍 짧은 메시지 — 원문 확인 권장
                        </div>
                      )}
                      <div className={`inline-block rounded-2xl px-3 py-1.5 text-xs whitespace-pre-wrap break-words ${tr.failed ? 'bg-rose-50 text-rose-700' : (isMine ? 'bg-sky-100 text-sky-900' : 'bg-amber-50 text-amber-900')}`}>
                        <span className="mr-1">{tr.failed ? '⚠️' : '🌐'}</span>
                        {tr.failed && <span className="font-bold mr-1">(번역 실패)</span>}
                        {tr.text}
                      </div>
                      {/* AI 자동 번역 disclaimer — 모든 번역에 작게 표기 (사용자 신뢰성 인지) */}
                      {!tr.failed && (
                        <div className={`text-[9px] text-slate-400 ${isMine ? 'text-right' : ''}`}>
                          ✦ AI 자동 번역 — 정확하지 않을 수 있어요
                        </div>
                      )}
                      {/* Phase 1-E3 만족도 피드백 — logId 있을 때만 (로그인+로그 성공) */}
                      {!tr.failed && tr.logId && user?.id && (
                        <div className={`flex items-center gap-1 text-[10px] ${isMine ? 'justify-end' : ''}`}>
                          {feedbacks[m.id] ? (
                            <span className="text-emerald-600 font-bold">
                              {feedbacks[m.id] === 1 ? '👍 고마워요' : '👎 더 나아질게요'}
                            </span>
                          ) : (
                            <>
                              <button
                                onClick={() => sendFeedback(m.id, tr.logId, 1)}
                                className="text-slate-400 hover:text-emerald-600 transition"
                                title="번역이 자연스러워요"
                              >👍</button>
                              <button
                                onClick={() => sendFeedback(m.id, tr.logId, -1)}
                                className="text-slate-400 hover:text-rose-600 transition"
                                title="번역이 어색해요"
                              >👎</button>
                            </>
                          )}
                        </div>
                      )}
                    </>
                    );
                  })()}
                  <div className={`flex items-center gap-2 text-[10px] text-slate-400 ${isMine ? 'justify-end' : ''}`}>
                    <span>{timeOf(m.created_at)}</span>
                    {/* 번역 트리거는 이름 옆 언어 칩으로 이동 (위 참조) */}
                    {isMine && (
                      <button
                        onClick={() => deleteOwn(m.id)}
                        className="text-rose-400 hover:underline opacity-0 group-hover:opacity-100 transition"
                      >
                        삭제
                      </button>
                    )}
                  </div>
                </div>
              )}
            </div>
          </div>
        </React.Fragment>
      );
    };

    return (
      <div className="flex flex-col h-full bg-white">
        {/* Header */}
        <div className="flex items-center gap-2 px-3 py-3 border-b border-slate-100 bg-white/90 backdrop-blur sticky top-0 z-10">
          {onBack && (
            <button onClick={onBack} className="flex h-9 w-9 items-center justify-center rounded-full hover:bg-slate-100" aria-label="뒤로">
              ←
            </button>
          )}
          <div className="text-xl flex-shrink-0">{roomEmoji}</div>
          <div className="flex-1 min-w-0">
            <div className="font-bold text-sm truncate">{roomName || '채팅'}</div>
            <div className="text-[11px] text-slate-500">
              {roomType === 'direct' ? '1:1 DM' : '그룹 채팅'} · 메시지는 90일간 보존
            </div>
          </div>
        </div>

        {/* Messages */}
        <div ref={scrollRef} className="flex-1 overflow-y-auto px-3 py-3 bg-slate-50/50">
          {loading && (
            <div className="py-10 text-center text-sm text-slate-400">메시지를 불러오는 중...</div>
          )}
          {loadError && (
            <div className="my-3 rounded-2xl bg-rose-50 px-4 py-3 text-sm text-rose-600">{loadError}</div>
          )}
          {!loading && !loadError && messages.length === 0 && (
            <div className="py-16 text-center text-sm text-slate-400" style={{ wordBreak: 'keep-all' }}>
              <div className="text-4xl mb-3">{roomEmoji}</div>
              <p className="font-bold text-base text-slate-700 mb-1">아직 메시지가 없어요</p>
              <p>가장 먼저 인사를 건네보세요!</p>
            </div>
          )}
          {messages.map((m, i) => renderMessage(m, messages[i - 1]))}
        </div>

        {/* Input */}
        <div className="border-t border-slate-100 bg-white px-3 py-3 flex items-end gap-2 sticky bottom-0">
          <input
            ref={fileInputRef}
            type="file"
            accept="image/*"
            className="hidden"
            onChange={onFileChange}
          />
          <button
            onClick={() => fileInputRef.current?.click()}
            disabled={uploading || sending}
            className="flex h-[42px] w-[42px] items-center justify-center rounded-full border-2 border-slate-100 text-slate-500 hover:border-sky-200 hover:text-sky-500 transition disabled:opacity-50"
            title="이미지 첨부 (최대 5MB)"
          >
            {uploading ? '⏳' : '🖼️'}
          </button>
          <textarea
            value={text}
            onChange={(e) => setText(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                send();
              }
            }}
            rows={1}
            maxLength={4000}
            placeholder="메시지를 입력하세요... (Enter로 전송, Shift+Enter 줄바꿈)"
            className="flex-1 resize-none rounded-2xl border-2 border-slate-100 px-4 py-2.5 text-sm outline-none focus:border-sky-300 max-h-32"
            style={{ minHeight: '42px' }}
          />
          <button
            onClick={send}
            disabled={sending || uploading || !text.trim()}
            className="rounded-full bg-sky-500 px-5 py-2.5 text-sm font-bold text-white disabled:bg-slate-300 hover:bg-sky-600 transition"
          >
            {sending ? '...' : '전송'}
          </button>
        </div>
      </div>
    );
  }

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