import React, {useState} from 'react'
import {Linking, Platform, Pressable, StyleSheet, Text, View} from 'react-native'
import {UpdateSDK} from '@xuqm/rn-sdk'

interface Props {
  appVersionCode: number
  rnModuleId: string
  rnCurrentVersion: string
  onLog: (msg: string) => void
}

type StepStatus = 'idle' | 'loading' | 'ok' | 'error'

interface CheckResult {
  needsUpdate: boolean
  label: string
  detail: string
}

export function UpdatePanel({appVersionCode, rnModuleId, rnCurrentVersion, onLog}: Props) {
  const [appStep, setAppStep] = useState<StepStatus>('idle')
  const [rnCheckStep, setRnCheckStep] = useState<StepStatus>('idle')
  const [rnDownloadStep, setRnDownloadStep] = useState<StepStatus>('idle')
  const [rnCacheStep, setRnCacheStep] = useState<StepStatus>('idle')

  const [appResult, setAppResult] = useState<CheckResult | null>(null)
  const [rnResult, setRnResult] = useState<CheckResult | null>(null)
  const [rnDownloadInfo, setRnDownloadInfo] = useState('')
  const [rnCacheInfo, setRnCacheInfo] = useState('')

  const reset = () => {
    setAppStep('idle')
    setRnCheckStep('idle')
    setRnDownloadStep('idle')
    setRnCacheStep('idle')
    setAppResult(null)
    setRnResult(null)
    setRnDownloadInfo('')
    setRnCacheInfo('')
  }

  const runAppUpdate = async () => {
    reset()
    setAppStep('loading')
    try {
      const res = await UpdateSDK.checkAppUpdate(appVersionCode)
      if (!res.needsUpdate) {
        setAppResult({
          needsUpdate: false,
          label: '✓ App 已是最新版本',
          detail: `当前版本码：${appVersionCode}，服务端无更高版本`,
        })
        setAppStep('ok')
        onLog('App 更新检查：当前最新')
        return
      }
      setAppResult({
        needsUpdate: true,
        label: `↑ 发现新版本 ${res.versionName ?? ''}（code=${res.versionCode ?? ''}）`,
        detail: [
          res.changeLog ? `更新说明：${res.changeLog}` : '',
          `强制更新：${res.forceUpdate ? '是' : '否'}`,
          res.downloadUrl ? `下载：${res.downloadUrl}` : '',
          res.appStoreUrl ? `App Store：${res.appStoreUrl}` : '',
        ].filter(Boolean).join('\n'),
      })
      setAppStep('ok')
      onLog(`发现 App 新版本：${res.versionName}`)
    } catch (e) {
      const msg = e instanceof Error ? e.message : 'App 更新检查失败'
      setAppResult({needsUpdate: false, label: '✗ 检查失败', detail: msg})
      setAppStep('error')
      onLog(`App 更新失败：${msg}`)
    }
  }

  const runRnUpdate = async () => {
    setRnCheckStep('loading')
    setRnDownloadStep('idle')
    setRnCacheStep('idle')
    setRnResult(null)
    setRnDownloadInfo('')
    setRnCacheInfo('')

    let checkInfo: Awaited<ReturnType<typeof UpdateSDK.checkRnUpdate>>
    try {
      checkInfo = await UpdateSDK.checkRnUpdate(rnModuleId, rnCurrentVersion)
      if (!checkInfo.needsUpdate) {
        setRnResult({
          needsUpdate: false,
          label: '✓ 插件已是最新版本',
          detail: `当前版本：${rnCurrentVersion}，服务端无更高版本`,
        })
        setRnCheckStep('ok')
        onLog('插件更新检查：当前最新')
        return
      }
      setRnResult({
        needsUpdate: true,
        label: `↑ 发现插件版本 ${checkInfo.latestVersion}（当前 ${rnCurrentVersion}）`,
        detail: [
          `模块：${rnModuleId}`,
          `平台：${Platform.OS}`,
          `md5：${checkInfo.md5}`,
          checkInfo.note ? `说明：${checkInfo.note}` : '',
          `minCommonVersion：${checkInfo.minCommonVersion}`,
        ].filter(Boolean).join('\n'),
      })
      setRnCheckStep('ok')
      onLog(`发现插件新版本：${checkInfo.latestVersion}`)
    } catch (e) {
      const msg = e instanceof Error ? e.message : '检查失败'
      setRnResult({needsUpdate: false, label: '✗ 检查失败', detail: msg})
      setRnCheckStep('error')
      onLog(`插件更新检查失败：${msg}`)
      return
    }

    // Step 2: Download
    setRnDownloadStep('loading')
    let source: string
    try {
      source = await UpdateSDK.downloadRnBundle(checkInfo.downloadUrl)
      setRnDownloadInfo(`下载完成，源码长度：${source.length} 字符`)
      setRnDownloadStep('ok')
      onLog(`插件 bundle 下载完成：${source.length} chars`)
    } catch (e) {
      const msg = e instanceof Error ? e.message : '下载失败'
      setRnDownloadInfo(`✗ 下载失败：${msg}`)
      setRnDownloadStep('error')
      onLog(`插件下载失败：${msg}`)
      return
    }

    // Step 3: Cache
    setRnCacheStep('loading')
    try {
      const cached = await UpdateSDK.cacheRnBundle(
        rnModuleId,
        checkInfo.latestVersion,
        checkInfo.md5,
        source,
      )
      setRnCacheInfo(
        `已写入 AsyncStorage\n版本：${cached.version}\nmd5：${cached.md5}\n时间：${cached.downloadedAt}`,
      )
      setRnCacheStep('ok')
      onLog(`插件 bundle 已缓存：${cached.version}`)
    } catch (e) {
      const msg = e instanceof Error ? e.message : '缓存失败'
      setRnCacheInfo(`✗ 缓存失败：${msg}`)
      setRnCacheStep('error')
      onLog(`插件缓存失败：${msg}`)
    }
  }

  const handleOpenDownload = () => {
    if (appResult?.detail) {
      const match = appResult.detail.match(/下载：(.+)/)
      const url = match?.[1]?.trim()
      if (url) Linking.openURL(url)
    }
  }

  return (
    <View style={styles.container}>
      {/* App 整包更新 */}
      <View style={styles.block}>
        <Text style={styles.blockTitle}>App 整包更新（APK / IPA）</Text>
        <Text style={styles.blockHint}>
          Android 返回 APK 下载链接，iOS 返回 App Store 跳转。
          本地版本码写死为 {appVersionCode}。
        </Text>
        <StepRow
          step={1}
          label="向服务端查询最新版本号"
          status={appStep}
          onPress={runAppUpdate}
          buttonText="检查 App 更新"
        />
        {appResult && (
          <ResultBox label={appResult.label} detail={appResult.detail} ok={appStep === 'ok' && !appResult.needsUpdate} />
        )}
        {appResult?.needsUpdate && appStep === 'ok' && (
          <Pressable onPress={handleOpenDownload} style={styles.openBtn}>
            <Text style={styles.openBtnText}>打开下载链接 ↗</Text>
          </Pressable>
        )}
      </View>

      {/* RN 插件热更新 */}
      <View style={styles.block}>
        <Text style={styles.blockTitle}>RN 插件热更新（JS Bundle）</Text>
        <Text style={styles.blockHint}>
          模块 <Text style={styles.mono}>{rnModuleId}</Text>，本地版本 <Text style={styles.mono}>{rnCurrentVersion}</Text>。
          热更新全流程：检查 → 下载 → 缓存至 AsyncStorage。
        </Text>

        <StepRow
          step={1}
          label="检查服务端是否有更高版本"
          status={rnCheckStep}
          onPress={runRnUpdate}
          buttonText="开始热更新流程"
        />
        {rnResult && (
          <ResultBox label={rnResult.label} detail={rnResult.detail} ok={rnCheckStep === 'ok' && !rnResult.needsUpdate} />
        )}

        {rnCheckStep === 'ok' && rnResult?.needsUpdate && (
          <>
            <StepRow
              step={2}
              label="下载 bundle 文件"
              status={rnDownloadStep}
            />
            {rnDownloadInfo ? (
              <ResultBox label={rnDownloadInfo} detail="" ok={rnDownloadStep === 'ok'} />
            ) : null}

            <StepRow
              step={3}
              label="写入本地缓存（AsyncStorage）"
              status={rnCacheStep}
            />
            {rnCacheInfo ? (
              <ResultBox label={rnCacheInfo} detail="" ok={rnCacheStep === 'ok'} />
            ) : null}
          </>
        )}
      </View>
    </View>
  )
}

function StepRow({
  step,
  label,
  status,
  onPress,
  buttonText,
}: {
  step: number
  label: string
  status: StepStatus
  onPress?: () => void
  buttonText?: string
}) {
  const icon = status === 'idle' ? '○' : status === 'loading' ? '⟳' : status === 'ok' ? '✓' : '✗'
  const iconColor = status === 'ok' ? '#22c55e' : status === 'error' ? '#ef4444' : status === 'loading' ? '#f59e0b' : '#9ca3af'

  return (
    <View style={styles.stepRow}>
      <Text style={[styles.stepIcon, {color: iconColor}]}>{icon}</Text>
      <View style={styles.stepBody}>
        <Text style={styles.stepLabel}>
          <Text style={styles.stepNum}>步骤 {step}：</Text>
          {label}
        </Text>
      </View>
      {onPress && buttonText && (
        <Pressable
          onPress={onPress}
          disabled={status === 'loading'}
          style={[styles.stepBtn, status === 'loading' && styles.btnDisabled]}>
          <Text style={styles.stepBtnText}>
            {status === 'loading' ? '检查中…' : buttonText}
          </Text>
        </Pressable>
      )}
    </View>
  )
}

function ResultBox({label, detail, ok}: {label: string; detail: string; ok: boolean}) {
  return (
    <View style={[styles.resultBox, ok ? styles.resultBoxOk : styles.resultBoxInfo]}>
      <Text style={styles.resultLabel}>{label}</Text>
      {detail ? <Text style={styles.resultDetail}>{detail}</Text> : null}
    </View>
  )
}

const styles = StyleSheet.create({
  container: {gap: 16},
  block: {gap: 10},
  blockTitle: {fontSize: 15, fontWeight: '800', color: '#1f2933'},
  blockHint: {fontSize: 13, lineHeight: 19, color: '#6b7280'},
  mono: {fontFamily: 'monospace', fontSize: 12},
  stepRow: {flexDirection: 'row', alignItems: 'center', gap: 8},
  stepIcon: {fontSize: 18, width: 24, textAlign: 'center'},
  stepBody: {flex: 1},
  stepLabel: {fontSize: 13, color: '#374151'},
  stepNum: {fontWeight: '700', color: '#1f2933'},
  stepBtn: {
    paddingHorizontal: 12,
    paddingVertical: 8,
    borderRadius: 12,
    backgroundColor: '#1f2933',
  },
  stepBtnText: {color: '#fff', fontSize: 12, fontWeight: '700'},
  btnDisabled: {opacity: 0.5},
  resultBox: {
    borderRadius: 12,
    padding: 10,
    gap: 4,
  },
  resultBoxOk: {backgroundColor: '#f0fdf4', borderWidth: 1, borderColor: '#86efac'},
  resultBoxInfo: {backgroundColor: '#fff7ed', borderWidth: 1, borderColor: '#fdba74'},
  resultLabel: {fontSize: 13, fontWeight: '600', color: '#1f2933'},
  resultDetail: {fontSize: 12, color: '#4b5563', lineHeight: 18, fontFamily: 'monospace'},
  openBtn: {
    minHeight: 40,
    borderRadius: 12,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#2563eb',
  },
  openBtnText: {color: '#fff', fontSize: 13, fontWeight: '700'},
})
