import React, {startTransition, useEffect, useRef, useState} from 'react'
import {
  Alert,
  Pressable,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  useColorScheme,
  View,
} from 'react-native'
import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context'
import {ImSDK, type ImEventListener, type ImMessage, type MsgType, UpdateSDK, XuqmSDK} from '@xuqm/rn-sdk'
import {MessageBubble} from './src/components/MessageBubble'
import {DEMO_CONTENT, MessageComposer} from './src/components/MessageComposer'
import {GroupChatPanel} from './src/components/GroupChatPanel'
import {UpdatePanel} from './src/components/UpdatePanel'
import pluginMeta from './plugin.json'

// Register this bundle as a plugin so UpdateSDK.checkRnUpdate() knows the current version.
UpdateSDK.registerPlugin(pluginMeta)

// Dev fallback: set app versionCode for simulators where native module is not linked.
UpdateSDK._devSetAppVersion(1, '1.0.0')

const APP_ID = 'ak_demo_chat'
const MODULE_ID = pluginMeta.moduleId

type DemoUser = {id: string; nickname: string}

const DEMO_USERS: DemoUser[] = [
  {id: 'demo_alice', nickname: 'Alice'},
  {id: 'demo_bob', nickname: 'Bob'},
]

const ALL_DEMO_TYPES: MsgType[] = [
  'TEXT', 'IMAGE', 'VIDEO', 'AUDIO', 'FILE', 'CUSTOM',
  'LOCATION', 'NOTIFY', 'RICH_TEXT', 'CALL_AUDIO', 'CALL_VIDEO', 'FORWARD',
]

function App() {
  const isDarkMode = useColorScheme() === 'dark'
  return (
    <SafeAreaProvider>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
      <SafeAreaView style={styles.safeArea}>
        <DemoConsole />
      </SafeAreaView>
    </SafeAreaProvider>
  )
}

function DemoConsole() {
  const [currentUser, setCurrentUser] = useState<DemoUser>(DEMO_USERS[0])
  const [connected, setConnected] = useState(false)
  const [singleMessages, setSingleMessages] = useState<ImMessage[]>([])
  const [groupMessages, setGroupMessages] = useState<ImMessage[]>([])
  const [sending, setSending] = useState(false)
  const [activityLog, setActivityLog] = useState<string[]>([])
  const activeUserRef = useRef(currentUser)
  const peerUser = DEMO_USERS.find(u => u.id !== currentUser.id) ?? DEMO_USERS[1]

  const appendLog = (msg: string) => {
    startTransition(() => {
      setActivityLog(prev =>
        [`[${new Date().toLocaleTimeString()}] ${msg}`, ...prev].slice(0, 30),
      )
    })
  }

  const mergeSingle = (message: ImMessage) => {
    startTransition(() => {
      setSingleMessages(prev => {
        const exists = prev.some(m => m.id === message.id)
        if (exists) return prev.map(m => m.id === message.id ? message : m)
        return [...prev, message].sort((a, b) => a.createdAt.localeCompare(b.createdAt))
      })
    })
  }

  const mergeGroup = (message: ImMessage) => {
    startTransition(() => {
      setGroupMessages(prev => {
        const exists = prev.some(m => m.id === message.id)
        if (exists) return prev.map(m => m.id === message.id ? message : m)
        return [...prev, message].sort((a, b) => a.createdAt.localeCompare(b.createdAt))
      })
    })
  }

  useEffect(() => {
    XuqmSDK.init({
      appId: APP_ID,
      debug: __DEV__,
    })
  }, [])

  useEffect(() => {
    activeUserRef.current = currentUser
  }, [currentUser])

  useEffect(() => {
    const listener: ImEventListener = {
      onConnected() {
        setConnected(true)
        appendLog(`WebSocket 已连接：${activeUserRef.current.nickname}`)
      },
      onDisconnected(reason) {
        setConnected(false)
        appendLog(`WebSocket 断开：${reason || 'unknown'}`)
      },
      onMessage(msg) {
        if (msg.chatType === 'SINGLE') mergeSingle(msg)
        else mergeGroup(msg)
        appendLog(`收到 [${msg.chatType}/${msg.msgType}] from ${msg.fromUserId}`)
      },
      onGroupMessage(msg) {
        mergeGroup(msg)
        appendLog(`收到群消息 [${msg.msgType}]`)
      },
      onError(error) {
        appendLog(`IM 错误：${error}`)
      },
    }
    ImSDK.addListener(listener)
    return () => {
      ImSDK.removeListener(listener)
      ImSDK.disconnect()
    }
  }, [])

  useEffect(() => {
    const run = async () => {
      try {
        ImSDK.disconnect()
        setConnected(false)
        setSingleMessages([])
        await ImSDK.login(currentUser.id, currentUser.nickname)
        appendLog(`已登录 IM：${currentUser.nickname}`)
        const history = await ImSDK.fetchHistory(peerUser.id, 0, 50)
        history.slice().reverse().forEach(m => mergeSingle(m))
        setConnected(ImSDK.isConnected())
      } catch (e) {
        const msg = e instanceof Error ? e.message : 'IM 登录失败'
        appendLog(`连接失败：${msg}`)
        Alert.alert('IM 登录失败', msg)
      }
    }
    run()
  }, [currentUser, peerUser.id])

  const handleSendSingle = async (msgType: MsgType, content: string) => {
    setSending(true)
    try {
      const sent = await ImSDK.sendMessage(peerUser.id, 'SINGLE', msgType, content)
      mergeSingle(sent)
      appendLog(`已发送 [${msgType}] 给 ${peerUser.nickname}`)
    } catch (e) {
      const msg = e instanceof Error ? e.message : '发送失败'
      appendLog(`发送失败 [${msgType}]：${msg}`)
      Alert.alert('发送失败', msg)
    } finally {
      setSending(false)
    }
  }

  const handleSendAllSingle = async () => {
    setSending(true)
    appendLog(`开始发送全部 ${ALL_DEMO_TYPES.length} 种消息类型（单聊）…`)
    for (const type of ALL_DEMO_TYPES) {
      const content = DEMO_CONTENT[type]
      if (!content) continue
      try {
        const sent = await ImSDK.sendMessage(peerUser.id, 'SINGLE', type, content)
        mergeSingle(sent)
        appendLog(`✓ [${type}]`)
        await new Promise<void>(resolve => setTimeout(resolve, 300))
      } catch (e) {
        appendLog(`✗ [${type}]：${e instanceof Error ? e.message : 'error'}`)
      }
    }
    appendLog('单聊全类型演示完成')
    setSending(false)
  }

  const handleRevokeSingle = async (messageId: string) => {
    try {
      const revoked = await ImSDK.revokeMessage(messageId)
      mergeSingle(revoked)
      appendLog(`消息已撤回：${messageId}`)
    } catch (e) {
      const msg = e instanceof Error ? e.message : '撤回失败'
      Alert.alert('撤回失败', msg)
    }
  }

  const handleReloadSingle = async () => {
    try {
      const history = await ImSDK.fetchHistory(peerUser.id, 0, 50)
      setSingleMessages(history.slice().reverse())
      appendLog(`历史消息已刷新，共 ${history.length} 条`)
    } catch (e) {
      appendLog(`历史拉取失败：${e instanceof Error ? e.message : 'error'}`)
    }
  }

  return (
    <ScrollView style={styles.scroll} contentContainerStyle={styles.content}>
      <Text style={styles.eyebrow}>XuqmGroup RN SDK Demo</Text>
      <Text style={styles.title}>IM · 全消息类型 · 群聊 · App 更新 · 热更新</Text>
      <Text style={styles.subtitle}>
        演示单聊/群聊全消息类型、整包更新和 RN 插件热更新完整流程。
      </Text>

      {/* Section 1: 当前会话 */}
      <SectionCard title="1. 当前会话">
        <View style={styles.userRow}>
          {DEMO_USERS.map(user => {
            const active = user.id === currentUser.id
            return (
              <Pressable
                key={user.id}
                onPress={() => setCurrentUser(user)}
                style={[styles.userChip, active && styles.userChipActive]}>
                <Text style={[styles.userChipText, active && styles.userChipTextActive]}>
                  {user.nickname}
                </Text>
              </Pressable>
            )
          })}
        </View>
        <Text style={styles.meta}>当前用户：{currentUser.nickname}（{currentUser.id}）</Text>
        <Text style={styles.meta}>单聊对象：{peerUser.nickname}（{peerUser.id}）</Text>
        <View style={styles.statusRow}>
          <View style={[styles.dot, connected ? styles.dotGreen : styles.dotGray]} />
          <Text style={styles.meta}>{connected ? 'IM 已连接' : '连接中 / 未连接'}</Text>
        </View>
        <View style={styles.row}>
          <PrimaryBtn title="刷新历史" onPress={handleReloadSingle} />
          <GhostBtn title="重新登录" onPress={() => {
            ImSDK.disconnect()
            setConnected(false)
            setSingleMessages([])
            ImSDK.login(currentUser.id, currentUser.nickname)
              .then(() => ImSDK.fetchHistory(peerUser.id, 0, 50))
              .then(h => { h.slice().reverse().forEach(m => mergeSingle(m)); setConnected(ImSDK.isConnected()) })
              .catch(e => appendLog(`重登录失败：${e instanceof Error ? e.message : 'error'}`))
          }} />
        </View>
      </SectionCard>

      {/* Section 2: 单聊 */}
      <SectionCard title="2. 单聊演示（全 12 种消息类型）">
        <Text style={styles.hint}>长按自己的消息可撤回。"全部类型演示"依次发送所有 12 种消息类型。</Text>
        <ScrollView
          style={styles.chatPanel}
          contentContainerStyle={styles.chatContent}
          showsVerticalScrollIndicator={false}>
          {singleMessages.length === 0 ? (
            <Text style={styles.empty}>还没有消息，发一条试试看。</Text>
          ) : (
            singleMessages.map(m => (
              <MessageBubble
                key={m.id}
                message={m}
                isOwn={m.fromUserId === currentUser.id}
                peerNickname={peerUser.nickname}
                onRevoke={handleRevokeSingle}
              />
            ))
          )}
        </ScrollView>
        <MessageComposer
          onSend={handleSendSingle}
          onSendAll={handleSendAllSingle}
          disabled={sending || !connected}
        />
      </SectionCard>

      {/* Section 3: 群聊 */}
      <SectionCard title="3. 群聊演示">
        <Text style={styles.hint}>
          点击"创建演示群"创建包含 Alice+Bob 的群组，"加载群列表"列出已有群，然后即可发送群消息。
        </Text>
        <GroupChatPanel
          currentUserId={currentUser.id}
          peerUserId={peerUser.id}
          peerNickname={peerUser.nickname}
          appId={APP_ID}
          onLog={appendLog}
          groupMessages={groupMessages}
          onMergeMessage={mergeGroup}
        />
      </SectionCard>

      {/* Section 4: 更新演示 */}
      <SectionCard title="4. 更新演示">
        <UpdatePanel
          rnModuleId={MODULE_ID}
          onLog={appendLog}
        />
      </SectionCard>

      {/* Section 5: 活动日志 */}
      <SectionCard title="5. 活动日志">
        {activityLog.length === 0 ? (
          <Text style={styles.empty}>暂无日志</Text>
        ) : (
          activityLog.map((item, i) => (
            <Text key={i} style={styles.logLine}>{item}</Text>
          ))
        )}
      </SectionCard>
    </ScrollView>
  )
}

function SectionCard({title, children}: {title: string; children: React.ReactNode}) {
  return (
    <View style={styles.card}>
      <Text style={styles.cardTitle}>{title}</Text>
      {children}
    </View>
  )
}

function PrimaryBtn({title, onPress, disabled}: {title: string; onPress: () => void; disabled?: boolean}) {
  return (
    <Pressable onPress={onPress} disabled={disabled} style={[styles.primaryBtn, disabled && styles.btnDisabled]}>
      <Text style={styles.primaryBtnText}>{title}</Text>
    </Pressable>
  )
}

function GhostBtn({title, onPress}: {title: string; onPress: () => void}) {
  return (
    <Pressable onPress={onPress} style={styles.ghostBtn}>
      <Text style={styles.ghostBtnText}>{title}</Text>
    </Pressable>
  )
}

const styles = StyleSheet.create({
  safeArea: {flex: 1, backgroundColor: '#f5efe3'},
  scroll: {flex: 1, backgroundColor: '#f5efe3'},
  content: {padding: 18, gap: 14, paddingBottom: 40},
  eyebrow: {fontSize: 13, fontWeight: '700', color: '#915f34', textTransform: 'uppercase', letterSpacing: 1.1},
  title: {fontSize: 26, lineHeight: 32, fontWeight: '800', color: '#1f2933'},
  subtitle: {fontSize: 13, lineHeight: 20, color: '#4b5563'},
  card: {borderRadius: 24, padding: 16, backgroundColor: '#fffaf2', borderWidth: 1, borderColor: '#ead7b7', gap: 12},
  cardTitle: {fontSize: 17, fontWeight: '800', color: '#1f2933'},
  hint: {fontSize: 13, lineHeight: 19, color: '#6b7280'},
  userRow: {flexDirection: 'row', gap: 10},
  userChip: {paddingHorizontal: 16, paddingVertical: 10, borderRadius: 999, backgroundColor: '#efe2c5'},
  userChipActive: {backgroundColor: '#1f2933'},
  userChipText: {color: '#4b5563', fontWeight: '700'},
  userChipTextActive: {color: '#fffdf8'},
  statusRow: {flexDirection: 'row', alignItems: 'center', gap: 6},
  dot: {width: 8, height: 8, borderRadius: 4},
  dotGreen: {backgroundColor: '#22c55e'},
  dotGray: {backgroundColor: '#9ca3af'},
  meta: {fontSize: 13, color: '#4b5563'},
  row: {flexDirection: 'row', gap: 10},
  chatPanel: {maxHeight: 340, borderRadius: 18, backgroundColor: '#f4ecdf'},
  chatContent: {padding: 12, gap: 6},
  empty: {fontSize: 14, color: '#7c7f85', textAlign: 'center', paddingVertical: 20},
  primaryBtn: {minHeight: 44, borderRadius: 14, alignItems: 'center', justifyContent: 'center', backgroundColor: '#1f2933', paddingHorizontal: 16},
  primaryBtnText: {color: '#fffdf8', fontSize: 14, fontWeight: '800'},
  ghostBtn: {minHeight: 44, borderRadius: 14, alignItems: 'center', justifyContent: 'center', backgroundColor: '#efe2c5', paddingHorizontal: 16},
  ghostBtnText: {color: '#4b5563', fontSize: 14, fontWeight: '700'},
  btnDisabled: {opacity: 0.45},
  logLine: {fontSize: 11, lineHeight: 17, color: '#374151', fontFamily: 'monospace'},
})

export default App
