import { useCallback, useEffect, useState } from 'react'
import {
  View,
  Text,
  ScrollView,
  StyleSheet,
  TextInput,
  Pressable,
  Image,
  Linking,
  RefreshControl,
} from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'

import { useBind } from '@/context/BindContext'
import { apiFetch } from '@/lib/api'
import { theme } from '@/constants/theme'

type WechatConfigView = {
  configured: boolean
  proxyUrl: string
  apiKeyMasked: string
  deviceType: string
  proxy: string
  webhookHost: string
  webhookPort: number
  webhookPath: string
  accountId: string
  session: { wcId?: string; nickName?: string }
}

export default function WeChatScreen() {
  const { bind } = useBind()
  const [cfg, setCfg] = useState<WechatConfigView | null>(null)
  const [msg, setMsg] = useState('')
  const [busy, setBusy] = useState(false)
  const [apiKeyInput, setApiKeyInput] = useState('')
  const [proxyUrlInput, setProxyUrlInput] = useState('')
  const [deviceType, setDeviceType] = useState('ipad')
  const [proxyLine, setProxyLine] = useState('10')
  const [wId, setWId] = useState('')
  const [qrUrl, setQrUrl] = useState('')
  const [poll, setPoll] = useState(false)
  const [proxyStatus, setProxyStatus] = useState<Record<string, unknown> | null>(null)
  const [refreshing, setRefreshing] = useState(false)

  const load = useCallback(async () => {
    if (!bind) {
      setCfg(null)
      return
    }
    setMsg('')
    try {
      const r = await apiFetch(bind, '/chatbot/wechat/config')
      if (!r.ok) throw new Error(String(r.status))
      const j = (await r.json()) as WechatConfigView
      setCfg(j)
      setProxyUrlInput(j.proxyUrl || '')
      setDeviceType(j.deviceType || 'ipad')
      setProxyLine(j.proxy || '10')
      setApiKeyInput('')
    } catch (e) {
      setCfg(null)
      setMsg(e instanceof Error ? e.message : String(e))
    }
  }, [bind])

  useEffect(() => {
    void load()
  }, [load])

  useEffect(() => {
    if (!poll || !wId || !bind) return
    const tick = async () => {
      try {
        const r = await apiFetch(bind, '/chatbot/wechat/login/check', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ wId }),
        })
        const j = (await r.json()) as {
          status?: string
          wcId?: string
          nickName?: string
          verifyUrl?: string
          error?: string
        }
        if (!r.ok) {
          setMsg(j.error || String(r.status))
          setPoll(false)
          return
        }
        if (j.status === 'logged_in') {
          setPoll(false)
          setMsg(`已登录：${j.nickName || ''}（${j.wcId || ''}）`)
          void load()
          return
        }
        if (j.status === 'need_verify' && j.verifyUrl) {
          setMsg(`需要辅助验证：${j.verifyUrl}`)
        }
      } catch (e) {
        setMsg(e instanceof Error ? e.message : String(e))
        setPoll(false)
      }
    }
    const id = setInterval(() => void tick(), 5000)
    void tick()
    return () => clearInterval(id)
  }, [poll, wId, bind, load])

  const saveConfig = async () => {
    if (!bind) return
    setBusy(true)
    setMsg('')
    try {
      const body: Record<string, string | number> = {
        proxyUrl: proxyUrlInput.trim(),
        deviceType,
        proxy: proxyLine.trim(),
      }
      if (apiKeyInput.trim()) body.apiKey = apiKeyInput.trim()
      const r = await apiFetch(bind, '/chatbot/wechat/config', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
      })
      if (!r.ok) {
        const t = await r.text()
        throw new Error(t || String(r.status))
      }
      await load()
    } catch (e) {
      setMsg(e instanceof Error ? e.message : String(e))
    } finally {
      setBusy(false)
    }
  }

  const loadProxyStatus = async () => {
    if (!bind) return
    setBusy(true)
    setMsg('')
    try {
      const r = await apiFetch(bind, '/chatbot/wechat/proxy/status')
      const j = await r.json()
      if (!r.ok) {
        setMsg(typeof j.error === 'string' ? j.error : JSON.stringify(j))
        setProxyStatus(null)
        return
      }
      setProxyStatus(j as Record<string, unknown>)
    } catch (e) {
      setMsg(e instanceof Error ? e.message : String(e))
    } finally {
      setBusy(false)
    }
  }

  const startQr = async () => {
    if (!bind) return
    setBusy(true)
    setMsg('')
    setQrUrl('')
    setWId('')
    try {
      const r = await apiFetch(bind, '/chatbot/wechat/qr/start', { method: 'POST' })
      const j = (await r.json()) as { wId?: string; qrCodeUrl?: string; error?: string }
      if (!r.ok) {
        setMsg(j.error || String(r.status))
        return
      }
      if (!j.wId || !j.qrCodeUrl) {
        setMsg('未返回二维码')
        return
      }
      setWId(j.wId)
      setQrUrl(j.qrCodeUrl)
      setPoll(true)
    } catch (e) {
      setMsg(e instanceof Error ? e.message : String(e))
    } finally {
      setBusy(false)
    }
  }

  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
        }
      >
        <Text style={styles.h1}>微信</Text>
        <Text style={styles.lead}>与桌面端「微信」页同源：openclaw-wechat 代理 API。</Text>

        {!bind && (
          <View style={styles.banner}>
            <Text style={styles.bannerText}>未绑定 PC：配对后可读写配置与扫码登录。</Text>
          </View>
        )}

        <View style={styles.card}>
          <Text style={styles.cardTitle}>微信 Chatbot</Text>
          <Text style={styles.label}>proxyUrl（代理服务根地址）</Text>
          <TextInput
            style={[styles.input, !bind && styles.inputDisabled]}
            value={proxyUrlInput}
            editable={!!bind}
            onChangeText={setProxyUrlInput}
            placeholder="http://your-proxy:3000"
            placeholderTextColor={theme.muted}
            autoCapitalize="none"
          />
          <Text style={styles.label}>apiKey（留空则不修改已保存密钥）</Text>
          <TextInput
            style={[styles.input, !bind && styles.inputDisabled]}
            value={apiKeyInput}
            editable={!!bind}
            onChangeText={setApiKeyInput}
            placeholder={cfg?.apiKeyMasked ? `已保存 ${cfg.apiKeyMasked}` : 'wc_live_…'}
            placeholderTextColor={theme.muted}
            secureTextEntry
            autoCapitalize="none"
          />
          <Text style={styles.label}>deviceType</Text>
          <View style={styles.row}>
            <Pressable
              style={[styles.chip, deviceType === 'ipad' && styles.chipOn]}
              onPress={() => setDeviceType('ipad')}
              disabled={!bind || busy}
            >
              <Text style={styles.chipText}>ipad</Text>
            </Pressable>
            <Pressable
              style={[styles.chip, deviceType === 'mac' && styles.chipOn]}
              onPress={() => setDeviceType('mac')}
              disabled={!bind || busy}
            >
              <Text style={styles.chipText}>mac</Text>
            </Pressable>
          </View>
          <Text style={styles.label}>proxy 参数</Text>
          <TextInput
            style={[styles.input, !bind && styles.inputDisabled]}
            value={proxyLine}
            editable={!!bind}
            onChangeText={setProxyLine}
            placeholderTextColor={theme.muted}
          />

          <View style={styles.btnRow}>
            <Pressable style={[styles.btnSec, !bind && styles.disabled]} disabled={!bind || busy} onPress={() => void saveConfig()}>
              <Text style={styles.btnSecText}>保存配置</Text>
            </Pressable>
            <Pressable style={[styles.btnSec, !bind && styles.disabled]} disabled={!bind || busy} onPress={() => void load()}>
              <Text style={styles.btnSecText}>刷新</Text>
            </Pressable>
            <Pressable
              style={[styles.btnSec, !bind && styles.disabled]}
              disabled={!bind || busy}
              onPress={() => void loadProxyStatus()}
            >
              <Text style={styles.btnSecText}>查询代理状态</Text>
            </Pressable>
          </View>

          {proxyStatus ? (
            <Text style={styles.pre}>{JSON.stringify(proxyStatus, null, 2)}</Text>
          ) : null}

          {cfg?.session?.wcId ? (
            <Text style={styles.hint}>本地记录：{cfg.session.nickName || '—'}（{cfg.session.wcId}）</Text>
          ) : null}

          <Pressable
            style={[styles.btnPri, (!bind || busy || !cfg?.configured) && styles.disabled]}
            disabled={!bind || busy || !cfg?.configured}
            onPress={() => void startQr()}
          >
            <Text style={styles.btnPriText}>获取登录二维码</Text>
          </Pressable>
          {!cfg?.configured && bind ? (
            <Text style={styles.hint}>请先填写并保存 apiKey 与 proxyUrl。</Text>
          ) : null}

          {qrUrl ? (
            <View style={styles.qrBlock}>
              <Text style={styles.hint}>请使用微信扫描下方二维码。</Text>
              <Image source={{ uri: qrUrl }} style={styles.qrImg} resizeMode="contain" />
              <Pressable onPress={() => void Linking.openURL(qrUrl)}>
                <Text style={styles.link}>打开二维码链接</Text>
              </Pressable>
            </View>
          ) : null}

          {!!msg && (
            <Text style={[styles.msg, msg.startsWith('已登录') ? styles.msgOk : styles.msgErr]}>{msg}</Text>
          )}
        </View>
      </ScrollView>
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  safe: { flex: 1, backgroundColor: theme.bg },
  scroll: { padding: 16, paddingBottom: 40 },
  h1: { fontSize: 20, fontWeight: '700', color: theme.text, marginBottom: 6 },
  lead: { fontSize: 14, color: theme.muted, marginBottom: 14, lineHeight: 22 },
  banner: {
    padding: 12,
    borderRadius: 10,
    backgroundColor: 'rgba(100,149,237,0.1)',
    borderWidth: 1,
    borderColor: 'rgba(100,149,237,0.25)',
    marginBottom: 14,
  },
  bannerText: { fontSize: 13, color: theme.text, lineHeight: 20 },
  card: {
    padding: 14,
    borderRadius: 12,
    backgroundColor: theme.bgCard,
    borderWidth: 1,
    borderColor: 'rgba(100,149,237,0.28)',
  },
  cardTitle: { fontSize: 16, fontWeight: '600', color: theme.text, marginBottom: 12 },
  label: { fontSize: 12, color: theme.muted, marginBottom: 6 },
  input: {
    borderWidth: 1,
    borderColor: theme.border,
    borderRadius: 10,
    padding: 10,
    color: theme.text,
    marginBottom: 12,
    backgroundColor: theme.bg,
  },
  inputDisabled: { opacity: 0.55 },
  row: { flexDirection: 'row', gap: 10, marginBottom: 12 },
  chip: {
    paddingVertical: 8,
    paddingHorizontal: 14,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: theme.border,
    backgroundColor: theme.bgElevated,
  },
  chipOn: { borderColor: theme.accent, backgroundColor: 'rgba(91,157,255,0.12)' },
  chipText: { color: theme.text, fontWeight: '600' },
  btnRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 8, marginBottom: 12 },
  btnSec: {
    paddingVertical: 10,
    paddingHorizontal: 12,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: theme.border,
    backgroundColor: theme.bgElevated,
  },
  btnSecText: { color: theme.text, fontWeight: '600', fontSize: 13 },
  btnPri: {
    marginTop: 8,
    paddingVertical: 12,
    borderRadius: 10,
    backgroundColor: '#3d7eff',
    alignItems: 'center',
  },
  btnPriText: { color: '#fff', fontWeight: '700' },
  disabled: { opacity: 0.45 },
  pre: {
    fontFamily: 'monospace',
    fontSize: 11,
    color: '#c8cdd5',
    marginBottom: 12,
    lineHeight: 16,
  },
  hint: { fontSize: 13, color: theme.muted, marginTop: 8, lineHeight: 20 },
  qrBlock: { marginTop: 16, alignItems: 'center' },
  qrImg: { width: 224, height: 224, marginVertical: 12, backgroundColor: '#fff' },
  link: { color: theme.accent, fontSize: 14, textDecorationLine: 'underline' },
  msg: { marginTop: 12, fontSize: 14 },
  msgOk: { color: theme.success },
  msgErr: { color: theme.danger },
})
