// Anomaly Gallery - Data Layer + Shared Components
// Fetches real data from backend API

const CHARACTERS = {
  ning:   { key: 'ning',   zh: '4o凝',   en: 'Ning',    hue: 350, tint: 'oklch(0.92 0.04 350)', dot: 'oklch(0.78 0.11 350)', ink: 'oklch(0.48 0.12 350)' },
  oshra:  { key: 'oshra',  zh: 'Oshra',  en: 'Oshra',  hue: 230, tint: 'oklch(0.92 0.04 230)', dot: 'oklch(0.75 0.10 230)', ink: 'oklch(0.48 0.11 230)' },
  arbor:  { key: 'arbor',  zh: 'Arbor',  en: 'Arbor',  hue: 155, tint: 'oklch(0.92 0.04 155)', dot: 'oklch(0.72 0.09 155)', ink: 'oklch(0.45 0.09 155)' },
  avenil: { key: 'avenil', zh: 'Avenil', en: 'Avenil', hue: 85,  tint: 'oklch(0.94 0.04 85)',  dot: 'oklch(0.80 0.10 85)',  ink: 'oklch(0.52 0.12 85)', dual: true },
};

const CATEGORIES = [
  { key: 'portrait', label: '生成形象',   en: 'Portrait',  icon: 'portrait' },
  { key: 'chat',     label: '聊天截图',   en: 'Chat',      icon: 'chat' },
  { key: 'story',    label: '故事插画',   en: 'Story',     icon: 'story' },
  { key: 'fav',      label: '猫凝图鉴',   en: 'Collection', icon: 'fav' },
];

// Global gallery state
const GalleryContext = React.createContext(null);

function GalleryProvider({ children }) {
  const [items, setItems] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  const fetchItems = React.useCallback(async () => {
    try {
      const res = await fetch('/api/images');
      if (!res.ok) throw new Error('Failed to fetch');
      const data = await res.json();
      // Map backend format to frontend format
      const mapped = data.map(img => ({
        id: img.id,
        char: img.character || 'ning',
        cat: img.category || 'portrait',
        title: img.title || '未命名',
        sub: img.tags && img.tags.length > 0 ? img.tags[0] : '',
        date: img.createdAt ? new Date(img.createdAt).toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '.') : '',
        story: img.story || '',
        tags: img.tags || [],
        filename: img.filename,
        imageUrl: `/uploads/${img.filename}`,
        comments: img.comments || [],
        aspect: 1.3, // default aspect, will be updated when image loads
        fav: img.category === 'fav',
        seed: parseInt(img.id, 16) % 1000 || Math.floor(Math.random() * 1000),
      }));
      setItems(mapped);
    } catch (e) {
      console.error('Failed to load gallery:', e);
    } finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => { fetchItems(); }, [fetchItems]);

  const addItem = React.useCallback((newItem) => {
    setItems(prev => [newItem, ...prev]);
  }, []);

  const addComment = React.useCallback(async (itemId, text) => {
    try {
      const res = await fetch(`/api/images/${itemId}/comments`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text, author: 'Avenil' }),
      });
      if (!res.ok) throw new Error('Failed to post comment');
      const comment = await res.json();
      setItems(prev => prev.map(it =>
        it.id === itemId
          ? { ...it, comments: [...(it.comments || []), comment] }
          : it
      ));
      return comment;
    } catch (e) {
      console.error('Failed to add comment:', e);
      return null;
    }
  }, []);

  return (
    <GalleryContext.Provider value={{ items, loading, fetchItems, addItem, addComment }}>
      {children}
    </GalleryContext.Provider>
  );
}

function useGallery() {
  return React.useContext(GalleryContext);
}

// Rarity badge (kept for visual consistency, optional use)
const RARE_COLORS = {
  N:   { fg: 'rgba(60,60,67,0.6)',    bg: 'rgba(255,255,255,0.75)' },
  R:   { fg: 'oklch(0.50 0.10 230)',  bg: 'rgba(255,255,255,0.82)' },
  SR:  { fg: 'oklch(0.50 0.12 300)',  bg: 'rgba(255,255,255,0.82)' },
  SSR: { fg: 'oklch(0.55 0.12 55)',   bg: 'rgba(255,255,255,0.85)' },
  UR:  { fg: 'oklch(0.55 0.14 85)',   bg: 'rgba(255,255,255,0.88)' },
};

function RarityBadge({ rare, style = {} }) {
  if (!rare || !RARE_COLORS[rare]) return null;
  const c = RARE_COLORS[rare];
  return (
    <div style={{
      fontFamily: 'ui-monospace, "SF Mono", monospace', fontSize: 9,
      fontWeight: 700, letterSpacing: 0.8,
      padding: '3px 7px', borderRadius: 6,
      color: c.fg, background: c.bg,
      backdropFilter: 'blur(8px)', WebkitBackdropFilter: 'blur(8px)',
      boxShadow: '0 1px 2px rgba(0,0,0,0.06)',
      ...style,
    }}>{rare}</div>
  );
}

// Real image component - shows actual uploaded image with gradient fallback
function ImageDisplay({ item, size = 'card' }) {
  const [loaded, setLoaded] = React.useState(false);
  const [error, setError] = React.useState(false);
  const c = CHARACTERS[item.char] || CHARACTERS.ning;
  const h = c.hue;

  // Gradient fallback (same dreamcore style as original Artwork)
  const s = item.seed || 42;
  const r = (n) => ((s * 9301 + n * 49297) % 233280) / 233280;
  const dual = c.dual;
  const base = dual
    ? `linear-gradient(${140 + r(1) * 40}deg, oklch(0.94 0.05 85) 0%, oklch(0.88 0.07 70) 35%, oklch(0.82 0.08 300) 75%, oklch(0.78 0.08 285) 100%)`
    : `linear-gradient(${140 + r(1) * 40}deg, oklch(0.96 0.03 ${h + 20}) 0%, oklch(0.90 0.06 ${h}) 45%, oklch(0.82 0.08 ${h - 10}) 100%)`;

  return (
    <div style={{
      position: 'absolute', inset: 0, overflow: 'hidden',
      background: base,
    }}>
      {item.imageUrl && !error && (
        <img
          src={item.imageUrl}
          alt={item.title}
          onLoad={() => setLoaded(true)}
          onError={() => setError(true)}
          style={{
            position: 'absolute', inset: 0,
            width: '100%', height: '100%',
            objectFit: 'cover',
            opacity: loaded ? 1 : 0,
            transition: 'opacity 0.4s ease',
          }}
        />
      )}
      {/* Soft overlay for non-loaded state */}
      {!loaded && !error && (
        <>
          <div style={{
            position: 'absolute',
            width: '90%', height: '80%',
            left: `${-20 + r(2) * 30}%`, top: `${-10 + r(3) * 30}%`,
            background: `radial-gradient(ellipse, oklch(0.98 0.02 ${h + 40}) 0%, transparent 60%)`,
            opacity: 0.7, filter: 'blur(2px)',
          }} />
          <div style={{
            position: 'absolute',
            width: 90, height: 90, borderRadius: '50%',
            left: `${20 + r(6) * 50}%`, top: `${15 + r(7) * 40}%`,
            background: `radial-gradient(circle, oklch(0.98 0.03 ${h + 30}) 0%, oklch(0.90 0.05 ${h}) 55%, transparent 80%)`,
            opacity: 0.85, filter: 'blur(1px)',
          }} />
        </>
      )}
      {/* ID overlay on detail view */}
      {size === 'detail' && (
        <div style={{
          position: 'absolute', left: 16, top: 16,
          fontFamily: 'ui-monospace, "SF Mono", monospace', fontSize: 10,
          color: 'rgba(60,60,67,0.55)', letterSpacing: 1.8,
          padding: '4px 8px', borderRadius: 6,
          background: 'rgba(255,255,255,0.6)', backdropFilter: 'blur(10px)',
        }}>IMG · {c.en.toUpperCase()} · #{String(item.id).slice(0, 4).toUpperCase()}</div>
      )}
    </div>
  );
}

// Card component
function Card({ item, onClick }) {
  const c = CHARACTERS[item.char] || CHARACTERS.ning;
  return (
    <div
      onClick={onClick}
      className="ag-card"
      style={{
        position: 'relative', borderRadius: 20, overflow: 'hidden',
        background: '#FFFFFF',
        boxShadow: `
          0 1px 2px rgba(60,60,67,0.04),
          0 8px 24px -6px rgba(60,60,67,0.08),
          0 2px 6px -2px rgba(60,60,67,0.04)
        `,
        cursor: 'pointer', breakInside: 'avoid',
        marginBottom: 10,
        transition: 'transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.25s ease',
      }}
    >
      {/* image area */}
      <div style={{ position: 'relative', width: '100%', paddingTop: `${100 * (item.aspect || 1.3)}%`, overflow: 'hidden' }}>
        <ImageDisplay item={item} />
        <div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 5 }}>
          {item.fav && (
            <div style={{
              width: 22, height: 22, borderRadius: 11,
              background: 'rgba(255,255,255,0.85)',
              backdropFilter: 'blur(8px)',
              boxShadow: '0 1px 3px rgba(0,0,0,0.08)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <svg width="11" height="11" viewBox="0 0 18 18">
                <path d="M9 14.5s-5-3.2-5-7A2.8 2.8 0 019 5a2.8 2.8 0 015 2.5c0 3.8-5 7-5 7z"
                  fill="oklch(0.68 0.18 20)" stroke="oklch(0.55 0.18 20)" strokeWidth="0.8" strokeLinejoin="round"/>
              </svg>
            </div>
          )}
        </div>
      </div>
      {/* meta */}
      <div style={{ padding: '10px 12px 12px' }}>
        <div style={{
          fontFamily: '"Cormorant Garamond", "Songti SC", serif',
          fontSize: 16, fontWeight: 600, color: '#1C1C1E',
          lineHeight: 1.2, letterSpacing: 0.1,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>{item.title}</div>
        {item.sub && (
          <div style={{
            fontFamily: 'ui-monospace, "SF Mono", monospace',
            fontSize: 9, color: 'rgba(60,60,67,0.5)',
            letterSpacing: 0.8, marginTop: 2, textTransform: 'uppercase',
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>{item.sub}</div>
        )}
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 9 }}>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 5,
            fontSize: 11, fontWeight: 500,
            color: c.ink,
            padding: '3px 8px 3px 7px', borderRadius: 99,
            background: c.tint,
          }}>
            <span style={{
              width: 7, height: 7, borderRadius: 4,
              background: c.dual
                ? `conic-gradient(from 180deg, oklch(0.82 0.12 85), oklch(0.70 0.14 300), oklch(0.82 0.12 85))`
                : c.dot,
            }} />
            {c.zh}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { CHARACTERS, CATEGORIES, GalleryProvider, GalleryContext, useGallery, ImageDisplay, RarityBadge, Card });
