import { useCallback, useEffect, useState } from 'react'
import { useFocusEffect } from 'expo-router'
import {
  View,
  Text,
  ScrollView,
  StyleSheet,
  RefreshControl,
  Pressable,
} from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'

import { useBind } from '@/context/BindContext'
import { apiFetch } from '@/lib/api'
import type { ClientOverview, NetworkPayload, RelayLivePayload, SystemMetricsPayload } from '@/lib/pcTypes'
import { getMultiChannelPro } from '@/lib/storage'
import { theme } from '@/constants/theme'

function fmtTs(ts: unknown): string {
  if (typeof ts !== 'number') return '—'
  try {
    return new Date(ts).toLocaleString()
  } catch {
    return '—'
  }
}

function fmtDur(sec: number | null | undefined): string {
  if (sec == null || Number.isNaN(sec)) return '—'
  const s = Math.floor(sec)
  const h = Math.floor(s / 3600)
  const m = Math.floor((s % 3600) / 60)
  const r = s % 60
  if (h > 0) return `${h}h${m}m${r}s`
  if (m > 0) return `${m}m${r}s`
  return `${r}s`
}

function SnapshotNet({ data }: { data: unknown }) {
  if (!data || typeof data !== 'object') return <Text style={styles.muted}>—</Text>
  const d = data as Record<string, unknown>
  if ('google' in d && 'douyin' in d) {
    const g = d.google as { reachable?: boolean; latency_ms?: number; country?: string }
    const y = d.douyin as { reachable?: boolean; latency_ms?: number; country?: string }
    return (
      <View style={styles.snapGrid}>
        <Text style={styles.snapLine}>
          Google {g?.reachable ? '可达' : '不可达'} ·{' '}
          {g?.latency_ms != null && g.latency_ms >= 0 ? `${g.latency_ms.toFixed(0)} ms` : '—'} · {g?.country ?? '—'}
        </Text>
        <Text style={styles.snapLine}>
          抖音 {y?.reachable ? '可达' : '不可达'} ·{' '}
          {y?.latency_ms != null && y.latency_ms >= 0 ? `${y.latency_ms.toFixed(0)} ms` : '—'} · {y?.country ?? '—'}
        </Text>
      </View>
    )
  }
  return <Text style={styles.muted}>—</Text>
}

function SnapshotSys({ data }: { data: unknown }) {
  if (!data || typeof data !== 'object') return <Text style={styles.muted}>—</Text>
  const d = data as Record<string, unknown>
  if ('cpu_percent' in d || 'memory' in d) {
    const mem = d.memory as { percent?: number } | undefined
    return (
      <View style={styles.snapGrid}>
        <Text style={styles.snapLine}>
          CPU {typeof d.cpu_percent === 'number' ? `${d.cpu_percent.toFixed(1)}%` : '—'}
        </Text>
        <Text style={styles.snapLine}>内存 {mem?.percent != null ? `${mem.percent.toFixed(1)}%` : '—'}</Text>
      </View>
    )
  }
  return <Text style={styles.muted}>—</Text>
}

export default function DeskScreen() {
  const { bind } = useBind()
  const [overview, setOverview] = useState<ClientOverview | null>(null)
  const [proLive, setProLive] = useState<RelayLivePayload | null>(null)
  const [proMode, setProMode] = useState(false)
  const [netSnap, setNetSnap] = useState<NetworkPayload | null>(null)
  const [sysSnap, setSysSnap] = useState<SystemMetricsPayload | null>(null)
  const [err, setErr] = useState('')
  const [refreshing, setRefreshing] = useState(false)

  const load = useCallback(async () => {
    if (!bind) {
      setOverview(null)
      setProLive(null)
      setNetSnap(null)
      setSysSnap(null)
      setErr('')
      return
    }
    setErr('')
    try {
      const r = await apiFetch(bind, '/client/overview')
      if (r.ok) setOverview((await r.json()) as ClientOverview)
      else setOverview(null)

      const multi = await getMultiChannelPro()
      setProMode(multi)
      if (multi) {
        const lr = await apiFetch(bind, '/relay_pro/live_status')
        if (lr.ok) setProLive((await lr.json()) as RelayLivePayload)
        else setProLive(null)
      } else {
        setProLive(null)
      }

      const nr = await apiFetch(bind, '/network_status')
      if (nr.ok) setNetSnap((await nr.json()) as NetworkPayload)
      else setNetSnap(null)

      const sr = await apiFetch(bind, '/system_metrics')
      if (sr.ok) setSysSnap((await sr.json()) as SystemMetricsPayload)
      else setSysSnap(null)
    } catch (e) {
      setErr(e instanceof Error ? e.message : String(e))
    }
  }, [bind])

  useFocusEffect(
    useCallback(() => {
      void load()
    }, [load]),
  )

  useEffect(() => {
    if (!bind || !proMode) return
    const id = setInterval(() => void load(), 12000)
    return () => clearInterval(id)
  }, [bind, proMode, load])

  const onRefresh = useCallback(async () => {
    setRefreshing(true)
    await load()
    setRefreshing(false)
  }, [load])

  return (
    <SafeAreaView style={styles.safe} edges={['bottom']}>
      <ScrollView
        contentContainerStyle={styles.scroll}
        refreshControl={
          bind ? (
            <RefreshControl refreshing={refreshing} onRefresh={() => void onRefresh()} tintColor={theme.accent} />
          ) : undefined
        }
      >
        <View style={styles.head}>
          <Text style={styles.h1}>仪表盘</Text>
          <Pressable style={styles.btnSec} disabled={!bind} onPress={() => void load()}>
            <Text style={styles.btnSecText}>刷新</Text>
          </Pressable>
        </View>
        <Text style={styles.lead}>
          与桌面端同源：概览、Pro 实况、网络/负载快照。事件与客户端日志仅在桌面端 SQLite。App 仅远程控制 PC，手机不运行 FFmpeg。
        </Text>

        {!bind && (
          <View style={styles.banner}>
            <Text style={styles.bannerText}>未绑定 PC：配对后显示频道摘要与转播状态。</Text>
          </View>
        )}

        {!!err && bind ? <Text style={styles.err}>{err}</Text> : null}

        {overview?.relayValidationErrors && overview.relayValidationErrors.length > 0 ? (
          <View style={styles.warnBox}>
            {overview.relayValidationErrors.map((x, i) => (
              <Text key={i} style={styles.warnText}>
                {x}
              </Text>
            ))}
          </View>
        ) : null}

        {proMode && (
          <View style={styles.card}>
            <Text style={styles.cardTitle}>Pro 转播实况</Text>
            <Text style={styles.meta}>
              {proLive?.youtubeProcess ?? '—'} · 状态 {proLive?.processStatus ?? '—'}{' '}
              {proLive?.processOnline ? (
                <Text style={styles.tagOn}>运行中</Text>
              ) : (
                <Text style={styles.tagOff}>未在运行</Text>
              )}
            </Text>
            {(proLive?.relayRows?.length ? proLive.relayRows : []).map((row, i) => (
              <View key={`${row.channelId ?? i}`} style={styles.liveRow}>
                <Text style={styles.liveTitle}>
                  {row.channelName || '未命名频道'} · key …{row.youtubeKeySuffix || '—'}
                </Text>
                <Text style={styles.liveLine}>主播 {row.anchor ?? '—'}</Text>
                <Text style={styles.liveLine} numberOfLines={2}>
                  抖音 {row.douyinHint ?? '—'}
                </Text>
                <Text style={styles.liveLine} numberOfLines={2}>
                  标题 {row.streamTitle ?? '—'}
                </Text>
                <Text style={styles.liveLine}>已播时长 {fmtDur(row.durationSec)}</Text>
              </View>
            ))}
            {!proLive?.relayRows?.length ? <Text style={styles.muted}>暂无实况</Text> : null}
          </View>
        )}

        <View style={styles.rowCards}>
          <View style={[styles.miniCard, { flex: 1 }]}>
            <Text style={styles.miniTitle}>网络快照</Text>
            <Text style={styles.miniMeta}>更新 {fmtTs(netSnap?.meta?.at)}</Text>
            <SnapshotNet data={netSnap as unknown} />
          </View>
          <View style={[styles.miniCard, { flex: 1 }]}>
            <Text style={styles.miniTitle}>本机负载快照</Text>
            <Text style={styles.miniMeta}>更新 {fmtTs(sysSnap?.ts)}</Text>
            <SnapshotSys data={sysSnap as unknown} />
          </View>
        </View>

        <View style={styles.card}>
          <Text style={styles.cardTitle}>直播与任务事件</Text>
          <Text style={styles.muted}>
            完整事件表、用户操作与客户端运行日志由桌面端本地数据库维护；请在 Windows 客户端查看明细。
          </Text>
        </View>
      </ScrollView>
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  safe: { flex: 1, backgroundColor: theme.bg },
  scroll: { padding: 16, paddingBottom: 40 },
  head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 },
  h1: { fontSize: 20, fontWeight: '700', color: theme.text },
  lead: { fontSize: 14, color: theme.muted, marginBottom: 14, lineHeight: 22 },
  banner: {
    padding: 12,
    borderRadius: 10,
    backgroundColor: 'rgba(91,157,255,0.1)',
    borderWidth: 1,
    borderColor: 'rgba(91,157,255,0.25)',
    marginBottom: 14,
  },
  bannerText: { fontSize: 13, color: theme.text, lineHeight: 20 },
  btnSec: {
    paddingVertical: 8,
    paddingHorizontal: 14,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: theme.border,
    backgroundColor: theme.bgElevated,
  },
  btnSecText: { color: theme.text, fontWeight: '600' },
  err: { color: theme.danger, marginBottom: 10 },
  warnBox: {
    padding: 10,
    borderRadius: 8,
    backgroundColor: 'rgba(245,101,101,0.1)',
    marginBottom: 12,
  },
  warnText: { color: theme.danger, fontSize: 13, marginBottom: 4 },
  card: {
    padding: 14,
    borderRadius: 12,
    backgroundColor: theme.bgCard,
    borderWidth: 1,
    borderColor: 'rgba(110,168,254,0.25)',
    marginBottom: 12,
  },
  cardTitle: { fontSize: 16, fontWeight: '600', color: theme.text, marginBottom: 10 },
  meta: { fontSize: 13, color: theme.muted, marginBottom: 8 },
  tagOn: { color: theme.success, fontWeight: '700' },
  tagOff: { color: theme.warn, fontWeight: '700' },
  liveRow: {
    paddingVertical: 10,
    borderTopWidth: 1,
    borderTopColor: theme.border,
  },
  liveTitle: { fontSize: 14, fontWeight: '600', color: theme.text, marginBottom: 4 },
  liveLine: { fontSize: 12, color: theme.muted, marginTop: 2 },
  rowCards: { flexDirection: 'row', gap: 10, marginBottom: 12 },
  miniCard: {
    padding: 12,
    borderRadius: 10,
    backgroundColor: theme.bgElevated,
    borderWidth: 1,
    borderColor: theme.border,
    minWidth: 0,
  },
  miniTitle: { fontSize: 13, fontWeight: '600', color: theme.text, marginBottom: 4 },
  miniMeta: { fontSize: 11, color: theme.muted, marginBottom: 8 },
  snapGrid: { gap: 6 },
  snapLine: { fontSize: 12, color: theme.text, lineHeight: 18 },
  muted: { fontSize: 13, color: theme.muted, lineHeight: 20 },
})
