/*
 * 라이브 공지 피드 — 공개 GET /api/public/events/{id}/live-notices.
 * 고정(pinned) 상단 우선 → 최신순(서버 정렬 신뢰). 긴급(URGENT) 강조. 30초 폴링.
 * 상태: 로딩·빈·degraded(마지막 데이터 유지 + 안내). 홈/행사 상세 공용.
 * 근거: src/backend/_workspace/cms_backlog_contract.md (공개 라이브 공지).
 */
import { Ionicons } from '@expo/vector-icons';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native';
import { isDegraded } from '../lib/api';
import { getLiveNotices } from '../lib/visitor';
import type { LiveNoticeCategory, LiveNoticeDto } from '../lib/types';
import { colors, radius, spacing, type } from '../theme';

const POLL_MS = 30_000;

/** 카테고리 → 배지 색(계약 권장 매핑). */
const CATEGORY_STYLE: Record<LiveNoticeCategory, { color: string; bg: string }> = {
  URGENT: { color: colors.error, bg: '#FEF3F2' },
  PROGRAM: { color: colors.warning, bg: '#FFF7ED' },
  INFO: { color: colors.primary700, bg: colors.primary050 },
  GENERAL: { color: colors.neutral700, bg: colors.neutral050 },
};

interface Props {
  eventId: string;
  /** 노출 최대 건수(홈=3 요약, 행사=전체). */
  max?: number;
}

export function LiveNoticeFeed({ eventId, max }: Props) {
  const { t } = useTranslation();
  const [items, setItems] = useState<LiveNoticeDto[] | null>(null);
  const [degraded, setDegraded] = useState(false);
  const mounted = useRef(true);

  const catLabel = useCallback(
    (c: LiveNoticeCategory): string => t(`notices.cat.${c}` as const),
    [t],
  );

  const load = useCallback(async () => {
    try {
      const res = await getLiveNotices(eventId, 100);
      if (!mounted.current) return;
      // 서버가 pinned 우선→최신 정렬. 방어적으로 pinned 재정렬(안정 정렬).
      const sorted = [...(res ?? [])].sort((a, b) => Number(b.pinned) - Number(a.pinned));
      setItems(sorted);
      setDegraded(false);
    } catch (e) {
      if (!mounted.current) return;
      setDegraded(isDegraded(e));
      setItems((prev) => prev ?? []); // 최초 실패는 빈 배열로(무한 로딩 방지)
    }
  }, [eventId]);

  useEffect(() => {
    mounted.current = true;
    load();
    const timer = setInterval(load, POLL_MS);
    return () => {
      mounted.current = false;
      clearInterval(timer);
    };
  }, [load]);

  const visible = max != null ? (items ?? []).slice(0, max) : items ?? [];

  return (
    <View style={styles.wrap}>
      <View style={styles.header}>
        <View style={styles.headerLeft}>
          <Ionicons name="megaphone-outline" size={18} color={colors.primary600} />
          <Text style={styles.title}>{t('notices.title')}</Text>
        </View>
        <View style={styles.liveDot}>
          <View style={styles.liveDotInner} />
          <Text style={styles.liveText}>{t('notices.live')}</Text>
        </View>
      </View>

      {items == null ? (
        <View style={styles.loading}>
          <ActivityIndicator color={colors.primary600} />
        </View>
      ) : visible.length === 0 ? (
        <Text style={styles.empty}>
          {degraded ? t('notices.degraded') : t('notices.empty')}
        </Text>
      ) : (
        <View style={styles.list}>
          {degraded ? <Text style={styles.degradedNote}>{t('notices.degraded')}</Text> : null}
          {visible.map((n) => (
            <NoticeRow key={n.id} notice={n} catLabel={catLabel} />
          ))}
        </View>
      )}
    </View>
  );
}

function NoticeRow({
  notice,
  catLabel,
}: {
  notice: LiveNoticeDto;
  catLabel: (c: LiveNoticeCategory) => string;
}) {
  const { t } = useTranslation();
  const urgent = notice.category === 'URGENT';
  const cat = CATEGORY_STYLE[notice.category] ?? CATEGORY_STYLE.GENERAL;
  return (
    <View style={[styles.row, urgent && styles.rowUrgent]}>
      <View style={styles.rowTop}>
        <View style={[styles.catBadge, { backgroundColor: cat.bg }]}>
          <Text style={[styles.catText, { color: cat.color }]}>{catLabel(notice.category)}</Text>
        </View>
        {notice.pinned ? (
          <View style={styles.pinBadge}>
            <Ionicons name="bookmark" size={10} color={colors.primary700} />
            <Text style={styles.pinText}>{t('notices.pinned')}</Text>
          </View>
        ) : null}
      </View>
      <Text style={[styles.rowTitle, urgent && { color: colors.error }]} numberOfLines={2}>
        {notice.title}
      </Text>
      {notice.body ? (
        <Text style={styles.rowBody} numberOfLines={2}>
          {notice.body}
        </Text>
      ) : null}
      {notice.authorName ? <Text style={styles.rowMeta}>{notice.authorName}</Text> : null}
    </View>
  );
}

const styles = StyleSheet.create({
  wrap: {
    backgroundColor: colors.white,
    borderWidth: 1,
    borderColor: colors.neutral200,
    borderRadius: radius.md,
    padding: spacing.md,
    gap: spacing.sm,
  },
  header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },
  headerLeft: { flexDirection: 'row', alignItems: 'center', gap: 6 },
  title: { fontSize: type.h3.fontSize, fontWeight: '700', color: colors.neutral900 },
  liveDot: { flexDirection: 'row', alignItems: 'center', gap: 5 },
  liveDotInner: { width: 6, height: 6, borderRadius: 3, backgroundColor: colors.error },
  liveText: { fontSize: 11, fontWeight: '700', color: colors.error },
  loading: { paddingVertical: spacing.md, alignItems: 'center' },
  empty: { fontSize: type.caption.fontSize, color: colors.neutral500, paddingVertical: spacing.sm },
  degradedNote: { fontSize: 11, color: colors.neutral500 },
  list: { gap: spacing.sm },
  row: {
    borderTopWidth: 1,
    borderTopColor: colors.neutral200,
    paddingTop: spacing.sm,
    gap: 4,
  },
  rowUrgent: { borderLeftWidth: 3, borderLeftColor: colors.error, paddingLeft: 8 },
  rowTop: { flexDirection: 'row', alignItems: 'center', gap: 6 },
  catBadge: { borderRadius: radius.sm, paddingHorizontal: 6, paddingVertical: 2 },
  catText: { fontSize: 10, fontWeight: '700' },
  pinBadge: { flexDirection: 'row', alignItems: 'center', gap: 3 },
  pinText: { fontSize: 10, fontWeight: '600', color: colors.primary700 },
  rowTitle: { fontSize: type.body.fontSize, fontWeight: '600', color: colors.neutral900 },
  rowBody: { fontSize: type.caption.fontSize, color: colors.neutral700, lineHeight: 18 },
  rowMeta: { fontSize: 11, color: colors.neutral500 },
});
