import React, {startTransition, useEffect, useRef, useState} from 'react';
import {
  Alert,
  Pressable,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  TextInput,
  useColorScheme,
  View,
} from 'react-native';
import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';
import {ImSDK, type ImEventListener, type ImMessage, UpdateSDK, XuqmSDK} from '@xuqm/rn-sdk';

const APP_ID = 'ak_demo_chat'
const MODULE_ID = 'chat-home'
const CURRENT_APP_VERSION_CODE = 1
const CURRENT_RN_VERSION = '1.0.0'
const API_BASE_URL = 'https://sentry.xuqinmin.com'
const IM_WS_URL = 'wss://sentry.xuqinmin.com/ws/im'

type DemoUser = {
  id: string
  nickname: string
}

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

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 [messages, setMessages] = useState<ImMessage[]>([])
  const [draft, setDraft] = useState('你好，我是 RN Demo。')
  const [activityLog, setActivityLog] = useState<string[]>([])
  const [appUpdateResult, setAppUpdateResult] = useState('点击“检查 App 更新”查看线上版本结果')
  const [rnUpdateResult, setRnUpdateResult] = useState('点击“检查插件更新”查看热更新结果')
  const [cachedBundleSummary, setCachedBundleSummary] = useState('暂无本地缓存')
  const activeUserRef = useRef(currentUser)
  const peerUser = DEMO_USERS.find(user => user.id !== currentUser.id) ?? DEMO_USERS[1]

  const appendLog = (message: string) => {
    startTransition(() => {
      setActivityLog(prev => [message, ...prev].slice(0, 12))
    })
  }

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

  const connectUser = async (user: DemoUser) => {
    try {
      ImSDK.disconnect()
      setConnected(false)
      setMessages([])
      await ImSDK.login(user.id, user.nickname)
      appendLog(`已登录 IM：${user.nickname}`)
      const history = await ImSDK.fetchHistory(peerUser.id, 0, 50)
      history
        .slice()
        .reverse()
        .forEach(item => mergeMessage(item))
      setConnected(ImSDK.isConnected())
    } catch (error) {
      const message = error instanceof Error ? error.message : 'IM 登录失败'
      appendLog(`连接失败：${message}`)
      Alert.alert('IM 登录失败', message)
    }
  }

  useEffect(() => {
    XuqmSDK.init({
      appId: APP_ID,
      appKey: APP_ID,
      appSecret: 'demo-secret-not-used-by-current-services',
      apiBaseUrl: API_BASE_URL,
      imWsUrl: IM_WS_URL,
      debug: true,
    })
  }, [])

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

  useEffect(() => {
    const listener: ImEventListener = {
      onConnected() {
        setConnected(true)
        appendLog(`WebSocket 已连接：${activeUserRef.current.nickname}`)
      },
      onDisconnected(reason) {
        setConnected(false)
        appendLog(`WebSocket 断开：${reason || 'unknown'}`)
      },
      onMessage(message) {
        mergeMessage(message)
      },
      onGroupMessage(message) {
        mergeMessage(message)
      },
      onError(error) {
        appendLog(`IM 错误：${error}`)
      },
    }

    ImSDK.addListener(listener)
    return () => {
      ImSDK.removeListener(listener)
      ImSDK.disconnect()
    }
  }, [])

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

    run()
  }, [currentUser, peerUser.id])

  useEffect(() => {
    UpdateSDK.getCachedRnBundle(MODULE_ID).then(bundle => {
      if (!bundle) return
      setCachedBundleSummary(`已缓存 ${bundle.version}，md5=${bundle.md5}`)
    })
  }, [])

  const handleSwitchUser = (user: DemoUser) => {
    setCurrentUser(user)
  }

  const handleSend = async () => {
    const content = draft.trim()
    if (!content) {
      return
    }

    try {
      const sent = await ImSDK.sendMessage(peerUser.id, 'SINGLE', 'TEXT', content)
      mergeMessage(sent)
      setDraft('')
      appendLog(`已发送给 ${peerUser.nickname}`)
    } catch (error) {
      const message = error instanceof Error ? error.message : '消息发送失败'
      appendLog(`发送失败：${message}`)
      Alert.alert('发送失败', message)
    }
  }

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

  const handleCheckAppUpdate = async () => {
    try {
      const result = await UpdateSDK.checkAppUpdate(CURRENT_APP_VERSION_CODE)
      if (!result.needsUpdate) {
        setAppUpdateResult('当前已是最新 App 版本')
        appendLog('App 更新检查：当前最新')
        return
      }
      setAppUpdateResult(
        `发现版本 ${result.versionName}（code=${result.versionCode}）\nforce=${String(result.forceUpdate)}\n下载地址：${result.downloadUrl || '未提供'}`,
      )
      appendLog(`发现 App 新版本：${result.versionName}`)
    } catch (error) {
      const message = error instanceof Error ? error.message : 'App 更新检查失败'
      setAppUpdateResult(message)
      appendLog(`App 更新失败：${message}`)
    }
  }

  const handleCheckRnUpdate = async () => {
    try {
      const result = await UpdateSDK.checkRnUpdate(MODULE_ID, CURRENT_RN_VERSION)
      if (!result.needsUpdate) {
        setRnUpdateResult('当前已是最新插件版本')
        appendLog('插件更新检查：当前最新')
        return
      }

      const source = await UpdateSDK.downloadRnBundle(result.downloadUrl)
      const cached = await UpdateSDK.cacheRnBundle(MODULE_ID, result.latestVersion, result.md5, source)
      setRnUpdateResult(
        `发现插件版本 ${result.latestVersion}\nmd5=${result.md5}\n说明：${result.note || '无'}\n已下载源码长度：${source.length}`,
      )
      setCachedBundleSummary(`已缓存 ${cached.version}，下载于 ${cached.downloadedAt}`)
      appendLog(`插件更新已缓存：${cached.version}`)
    } catch (error) {
      const message = error instanceof Error ? error.message : '插件更新检查失败'
      setRnUpdateResult(message)
      appendLog(`插件更新失败：${message}`)
    }
  }

  return (
    <ScrollView style={styles.container} contentContainerStyle={styles.content}>
      <Text style={styles.heroEyebrow}>XuqmGroup RN SDK Demo</Text>
      <Text style={styles.heroTitle}>聊天、App 更新、插件热更新一屏演示</Text>
      <Text style={styles.heroSubtitle}>
        这个项目直接连接 {API_BASE_URL}，默认使用两个演示用户互聊。
      </Text>

      <SectionCard title="1. 当前会话">
        <View style={styles.userSwitcher}>
          {DEMO_USERS.map(user => {
            const active = user.id === currentUser.id
            return (
              <Pressable
                key={user.id}
                onPress={() => {
                  handleSwitchUser(user)
                }}
                style={[styles.userChip, active && styles.userChipActive]}>
                <Text style={[styles.userChipText, active && styles.userChipTextActive]}>
                  {user.nickname}
                </Text>
              </Pressable>
            )
          })}
        </View>
        <Text style={styles.metaText}>当前用户：{currentUser.nickname}（{currentUser.id}）</Text>
        <Text style={styles.metaText}>聊天对象：{peerUser.nickname}（{peerUser.id}）</Text>
        <Text style={styles.metaText}>连接状态：{connected ? '已连接' : '连接中 / 未连接'}</Text>
        <View style={styles.inlineActions}>
          <PrimaryButton title="重新拉历史" onPress={() => {
            handleReloadHistory()
          }} />
          <GhostButton title="重新登录" onPress={() => {
            connectUser(currentUser)
          }} />
        </View>
      </SectionCard>

      <SectionCard title="2. 聊天演示">
        <View style={styles.chatPanel}>
          {messages.length === 0 ? (
            <Text style={styles.emptyText}>还没有消息，发一条试试看。</Text>
          ) : (
            messages.map(message => {
              const mine = message.fromUserId === currentUser.id
              return (
                <View
                  key={message.id}
                  style={[styles.bubbleRow, mine ? styles.bubbleRowMine : styles.bubbleRowPeer]}>
                  <View style={[styles.bubble, mine ? styles.bubbleMine : styles.bubblePeer]}>
                    <Text style={styles.bubbleMeta}>
                      {mine ? '我' : peerUser.nickname} · {message.msgType}
                    </Text>
                    <Text style={styles.bubbleText}>{message.content}</Text>
                  </View>
                </View>
              )
            })
          )}
        </View>
        <TextInput
          value={draft}
          onChangeText={setDraft}
          placeholder="输入一条消息"
          placeholderTextColor="#7c7f85"
          style={styles.input}
        />
        <PrimaryButton title="发送消息" onPress={() => {
          handleSend()
        }} />
      </SectionCard>

      <SectionCard title="3. App 更新演示">
        <Text style={styles.paragraph}>
          当前本地版本号写死为 {CURRENT_APP_VERSION_CODE}，方便你在服务端发布更高版本后立即观察效果。
        </Text>
        <PrimaryButton title="检查 App 更新" onPress={() => {
          handleCheckAppUpdate()
        }} />
        <Text style={styles.resultText}>{appUpdateResult}</Text>
      </SectionCard>

      <SectionCard title="4. 插件热更新演示">
        <Text style={styles.paragraph}>
          当前模块：{MODULE_ID}，本地插件版本：{CURRENT_RN_VERSION}。
        </Text>
        <PrimaryButton title="检查插件更新并缓存" onPress={() => {
          handleCheckRnUpdate()
        }} />
        <Text style={styles.resultText}>{rnUpdateResult}</Text>
        <Text style={styles.cacheText}>{cachedBundleSummary}</Text>
      </SectionCard>

      <SectionCard title="5. 活动日志">
        {activityLog.length === 0 ? (
          <Text style={styles.emptyText}>暂无日志</Text>
        ) : (
          activityLog.map(item => (
            <Text key={item} 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 PrimaryButton({title, onPress}: {title: string; onPress: () => void}) {
  return (
    <Pressable onPress={onPress} style={styles.primaryButton}>
      <Text style={styles.primaryButtonText}>{title}</Text>
    </Pressable>
  )
}

function GhostButton({title, onPress}: {title: string; onPress: () => void}) {
  return (
    <Pressable onPress={onPress} style={styles.ghostButton}>
      <Text style={styles.ghostButtonText}>{title}</Text>
    </Pressable>
  )
}

const styles = StyleSheet.create({
  safeArea: {
    flex: 1,
    backgroundColor: '#f5efe3',
  },
  container: {
    flex: 1,
    backgroundColor: '#f5efe3',
  },
  content: {
    padding: 18,
    gap: 14,
  },
  heroEyebrow: {
    fontSize: 13,
    fontWeight: '700',
    color: '#915f34',
    textTransform: 'uppercase',
    letterSpacing: 1.1,
  },
  heroTitle: {
    fontSize: 30,
    lineHeight: 36,
    fontWeight: '800',
    color: '#1f2933',
  },
  heroSubtitle: {
    fontSize: 15,
    lineHeight: 22,
    color: '#4b5563',
  },
  card: {
    borderRadius: 24,
    padding: 16,
    backgroundColor: '#fffaf2',
    borderWidth: 1,
    borderColor: '#ead7b7',
    gap: 12,
  },
  cardTitle: {
    fontSize: 19,
    fontWeight: '800',
    color: '#1f2933',
  },
  userSwitcher: {
    flexDirection: 'row',
    gap: 10,
  },
  userChip: {
    paddingHorizontal: 14,
    paddingVertical: 10,
    borderRadius: 999,
    backgroundColor: '#efe2c5',
  },
  userChipActive: {
    backgroundColor: '#1f2933',
  },
  userChipText: {
    color: '#4b5563',
    fontWeight: '700',
  },
  userChipTextActive: {
    color: '#fffdf8',
  },
  metaText: {
    fontSize: 14,
    color: '#4b5563',
  },
  inlineActions: {
    flexDirection: 'row',
    gap: 10,
  },
  chatPanel: {
    maxHeight: 340,
    borderRadius: 18,
    backgroundColor: '#f4ecdf',
    padding: 12,
    gap: 8,
  },
  bubbleRow: {
    flexDirection: 'row',
  },
  bubbleRowMine: {
    justifyContent: 'flex-end',
  },
  bubbleRowPeer: {
    justifyContent: 'flex-start',
  },
  bubble: {
    maxWidth: '85%',
    borderRadius: 18,
    paddingHorizontal: 12,
    paddingVertical: 10,
    gap: 4,
  },
  bubbleMine: {
    backgroundColor: '#cae7d8',
  },
  bubblePeer: {
    backgroundColor: '#ffffff',
    borderWidth: 1,
    borderColor: '#ddd3c2',
  },
  bubbleMeta: {
    fontSize: 11,
    color: '#6b7280',
    fontWeight: '700',
  },
  bubbleText: {
    fontSize: 15,
    lineHeight: 21,
    color: '#111827',
  },
  input: {
    minHeight: 48,
    borderRadius: 16,
    borderWidth: 1,
    borderColor: '#dac8a8',
    backgroundColor: '#fff',
    paddingHorizontal: 14,
    color: '#111827',
  },
  paragraph: {
    fontSize: 14,
    lineHeight: 21,
    color: '#4b5563',
  },
  primaryButton: {
    minHeight: 46,
    borderRadius: 16,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#1f2933',
    paddingHorizontal: 16,
  },
  primaryButtonText: {
    color: '#fffdf8',
    fontSize: 15,
    fontWeight: '800',
  },
  ghostButton: {
    minHeight: 46,
    borderRadius: 16,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#efe2c5',
    paddingHorizontal: 16,
  },
  ghostButtonText: {
    color: '#4b5563',
    fontSize: 15,
    fontWeight: '800',
  },
  resultText: {
    fontSize: 14,
    lineHeight: 21,
    color: '#1f2933',
  },
  cacheText: {
    fontSize: 13,
    color: '#6b7280',
  },
  emptyText: {
    fontSize: 14,
    color: '#7c7f85',
  },
  logLine: {
    fontSize: 13,
    lineHeight: 20,
    color: '#374151',
  },
})

export default App
