/**
 * Devices screen — Settings → Linked devices.
 *
 * Multi-device registry (v2.2.0). Lists every X25519 device published
 * on-chain under this identity's master Ed25519 key. Operators can:
 *   - see added-at timestamps
 *   - rename this device (local alias for now; rename via LINK_DEVICE
 *     with same pub + new name is a v2.3 polish)
 *   - revoke a remote device via UNLINK_DEVICE (requires fee)
 *   - pair a new device (Phase 3 — separate modal, stub for now)
 *
 * This device is NEVER listed with an Unlink button — revoking yourself
 * is a footgun (you'd wipe your own state on next launch). Export/import
 * your key first, then revoke from the new device.
 */
import React, { useCallback, useEffect, useState } from 'react';
import {
  View, Text, ScrollView, Pressable, ActivityIndicator, Alert, RefreshControl,
  TextInput, KeyboardAvoidingView, Platform, Modal,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

import { useStore } from '@/lib/store';
import {
  fetchDevices, buildLinkDeviceTx, buildUnlinkDeviceTx, submitTx,
  sendEnvelope, humanizeTxError,
  type DeviceInfo,
} from '@/lib/api';
import { encryptMessage } from '@/lib/crypto';
import { Header } from '@/components/Header';
import { IconButton } from '@/components/IconButton';
import { safeBack } from '@/lib/utils';

function shortPub(p: string, n = 8): string {
  if (!p) return '—';
  return p.length <= n * 2 + 1 ? p : `${p.slice(0, n)}…${p.slice(-n)}`;
}

function formatDate(unixSec: number): string {
  return new Date(unixSec * 1000).toLocaleString();
}

export default function DevicesScreen() {
  const insets  = useSafeAreaInsets();
  const keyFile = useStore(s => s.keyFile);

  const [devices, setDevices]       = useState<DeviceInfo[]>([]);
  const [loading, setLoading]       = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [unlinking, setUnlinking]   = useState<string | null>(null); // pub being revoked

  const load = useCallback(async (isRefresh = false) => {
    if (!keyFile) return;
    if (isRefresh) setRefreshing(true);
    else setLoading(true);
    try {
      const list = await fetchDevices(keyFile.pub_key);
      setDevices(list);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  }, [keyFile]);

  useEffect(() => { load(false); }, [load]);

  const onUnlink = useCallback((dev: DeviceInfo) => {
    if (!keyFile) return;
    Alert.alert(
      'Unlink device?',
      `"${dev.device_name}" will stop receiving messages sent to you. ` +
      `This costs a small network fee. The revoked device wipes its ` +
      `local state the next time it checks in.`,
      [
        { text: 'Cancel', style: 'cancel' },
        {
          text: 'Unlink',
          style: 'destructive',
          onPress: async () => {
            setUnlinking(dev.x25519_pub_key);
            try {
              const tx = buildUnlinkDeviceTx({
                from:      keyFile.pub_key,
                x25519Pub: dev.x25519_pub_key,
                privKey:   keyFile.priv_key,
              });
              await submitTx(tx);
              // Optimistic — drop from local list immediately; next load
              // reconciles. Chain tx takes ~1 block to commit.
              setDevices(prev => prev.filter(d => d.x25519_pub_key !== dev.x25519_pub_key));
            } catch (e: any) {
              Alert.alert('Unlink failed', humanizeTxError(e));
            } finally {
              setUnlinking(null);
            }
          },
        },
      ],
    );
  }, [keyFile]);

  const meX25519 = keyFile?.x25519_pub ?? '';

  // Pairing modal state — filled by the operator reading values off the
  // new device's /auth/pair screen.
  const [pairOpen, setPairOpen]             = useState(false);
  const [pairCode, setPairCode]             = useState('');
  const [pairKey,  setPairKey]              = useState('');
  const [pairName, setPairName]             = useState('');
  const [pairBusy, setPairBusy]             = useState(false);

  const submitPair = useCallback(async () => {
    if (!keyFile) return;
    const code = pairCode.replace(/\s+/g, '').trim();
    const key  = pairKey.replace(/\s+/g, '').trim().toLowerCase();
    if (!/^\d{6}$/.test(code)) {
      Alert.alert('Invalid code', 'The pairing code is 6 digits.');
      return;
    }
    if (!/^[0-9a-f]{64}$/.test(key)) {
      Alert.alert('Invalid key', 'The device key must be 64 hex characters.');
      return;
    }
    const name = pairName.trim() || 'New device';
    setPairBusy(true);
    try {
      // 1. LINK_DEVICE on-chain so senders learn the new pub.
      const tx = buildLinkDeviceTx({
        from:       keyFile.pub_key,
        x25519Pub:  key,
        deviceName: name,
        privKey:    keyFile.priv_key,
      });
      await submitTx(tx);
      // 2. Ship the handshake payload to the new device. Encrypted for
      //    its x25519 pub so only it can read — master priv in plaintext
      //    would be catastrophic, E2E is the whole point.
      const payload = JSON.stringify({
        v: 1,
        type: 'pair-handshake',
        code,
        master_pub:        keyFile.pub_key,
        master_priv:       keyFile.priv_key,
        master_x25519_pub: keyFile.x25519_pub,
      });
      const { nonce, ciphertext } = encryptMessage(
        payload, keyFile.x25519_priv, key,
      );
      await sendEnvelope({
        senderPub:    keyFile.x25519_pub,
        recipientPub: key,
        senderEd25519Pub: keyFile.pub_key,
        nonce, ciphertext,
      });
      // 3. Optimistic local insert so the row shows up without waiting
      //    for the next pull/refresh round-trip.
      setDevices(prev => {
        if (prev.some(d => d.x25519_pub_key === key)) return prev;
        return [...prev, {
          x25519_pub_key: key,
          device_name:    name,
          added_at:       Math.floor(Date.now() / 1000),
        }];
      });
      setPairOpen(false);
      setPairCode(''); setPairKey(''); setPairName('');
      Alert.alert(
        'Pairing sent',
        'The new device should finish pairing in a few seconds.',
      );
    } catch (e: any) {
      Alert.alert('Pairing failed', humanizeTxError(e));
    } finally {
      setPairBusy(false);
    }
  }, [keyFile, pairCode, pairKey, pairName]);

  return (
    <View style={{ flex: 1, backgroundColor: '#000000', paddingTop: insets.top }}>
      <Header
        title="Devices"
        divider
        left={<IconButton icon="chevron-back" size={36} onPress={() => safeBack()} />}
      />

      <ScrollView
        contentContainerStyle={{ padding: 14, paddingBottom: insets.bottom + 30 }}
        refreshControl={
          <RefreshControl
            refreshing={refreshing}
            onRefresh={() => load(true)}
            tintColor="#1d9bf0"
          />
        }
      >
        <Text style={{ color: '#8b8b8b', fontSize: 12, lineHeight: 17, marginBottom: 14 }}>
          Every linked device has its own encryption key. Messages sent to you
          are delivered to all active devices.
        </Text>

        {loading ? (
          <View style={{ paddingTop: 60, alignItems: 'center' }}>
            <ActivityIndicator color="#1d9bf0" />
          </View>
        ) : devices.length === 0 ? (
          <View style={{
            paddingTop: 60, alignItems: 'center', paddingHorizontal: 24,
          }}>
            <Ionicons name="phone-portrait-outline" size={36} color="#3a3a3a" />
            <Text style={{
              color: '#ffffff', fontSize: 15, fontWeight: '700',
              marginTop: 10,
            }}>
              No devices registered yet
            </Text>
            <Text style={{
              color: '#8b8b8b', fontSize: 13, textAlign: 'center',
              marginTop: 6, lineHeight: 19,
            }}>
              This device auto-registers when the next network-fee is available.
              Top up your balance and pull to refresh.
            </Text>
          </View>
        ) : (
          <View style={{
            borderRadius: 14,
            backgroundColor: '#0a0a0a',
            borderWidth: 1, borderColor: '#1f1f1f',
            overflow: 'hidden',
          }}>
            {devices.map((d, i) => {
              const isMe = d.x25519_pub_key === meX25519;
              const busy = unlinking === d.x25519_pub_key;
              return (
                <View key={d.x25519_pub_key}>
                  {i > 0 && <View style={{ height: 1, backgroundColor: '#1f1f1f' }} />}
                  <View style={{
                    flexDirection: 'row', alignItems: 'center',
                    paddingHorizontal: 14, paddingVertical: 14, gap: 12,
                  }}>
                    <Ionicons
                      name={isMe ? 'phone-portrait' : 'phone-portrait-outline'}
                      size={22}
                      color={isMe ? '#1d9bf0' : '#d0d0d0'}
                    />
                    <View style={{ flex: 1, minWidth: 0 }}>
                      <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
                        <Text
                          style={{ color: '#ffffff', fontSize: 15, fontWeight: '700' }}
                          numberOfLines={1}
                        >
                          {d.device_name || 'Unnamed device'}
                        </Text>
                        {isMe && (
                          <View style={{
                            paddingHorizontal: 6, paddingVertical: 1,
                            borderRadius: 6, backgroundColor: '#0d2540',
                          }}>
                            <Text style={{ color: '#1d9bf0', fontSize: 10, fontWeight: '700' }}>
                              THIS DEVICE
                            </Text>
                          </View>
                        )}
                      </View>
                      <Text
                        style={{
                          color: '#8b8b8b', fontSize: 11, fontFamily: 'monospace',
                          marginTop: 3,
                        }}
                        numberOfLines={1}
                      >
                        {shortPub(d.x25519_pub_key)}
                      </Text>
                      <Text style={{ color: '#6a6a6a', fontSize: 11, marginTop: 2 }}>
                        Linked {formatDate(d.added_at)}
                      </Text>
                    </View>
                    {!isMe && (
                      <Pressable
                        onPress={() => onUnlink(d)}
                        disabled={busy}
                        style={({ pressed }) => ({
                          paddingHorizontal: 12, paddingVertical: 7,
                          borderRadius: 999,
                          borderWidth: 1, borderColor: '#3a2020',
                          backgroundColor: pressed ? '#2a1414' : 'transparent',
                          opacity: busy ? 0.5 : 1,
                        })}
                      >
                        {busy ? (
                          <ActivityIndicator size="small" color="#ff6b6b" />
                        ) : (
                          <Text style={{ color: '#ff6b6b', fontSize: 12, fontWeight: '700' }}>
                            Unlink
                          </Text>
                        )}
                      </Pressable>
                    )}
                  </View>
                </View>
              );
            })}
          </View>
        )}

        {/* Link new device — opens a modal with Code + DeviceKey inputs
            that the operator transcribes from the new device's
            /auth/pair screen. */}
        <View style={{ marginTop: 18 }}>
          <Pressable
            onPress={() => setPairOpen(true)}
            style={({ pressed }) => ({
              paddingVertical: 13, paddingHorizontal: 16,
              borderRadius: 14,
              backgroundColor: pressed ? '#1a1a1a' : '#0a0a0a',
              borderWidth: 1, borderColor: '#1f1f1f',
              flexDirection: 'row', alignItems: 'center', gap: 10,
            })}
          >
            <Ionicons name="link-outline" size={18} color="#1d9bf0" />
            <View style={{ flex: 1 }}>
              <Text style={{ color: '#ffffff', fontSize: 14, fontWeight: '700' }}>
                Link new device
              </Text>
              <Text style={{ color: '#8b8b8b', fontSize: 12, marginTop: 2 }}>
                Enter the 6-digit code from the new device
              </Text>
            </View>
            <Ionicons name="chevron-forward" size={18} color="#6a6a6a" />
          </Pressable>
        </View>
      </ScrollView>

      {/* ── Pair new device modal ───────────────────────────────────── */}
      <Modal
        visible={pairOpen}
        animationType="fade"
        transparent
        onRequestClose={() => !pairBusy && setPairOpen(false)}
      >
        <KeyboardAvoidingView
          behavior={Platform.OS === 'ios' ? 'padding' : undefined}
          style={{
            flex: 1,
            backgroundColor: 'rgba(0,0,0,0.7)',
            justifyContent: 'center', alignItems: 'center',
            paddingHorizontal: 20,
          }}
        >
          <View style={{
            width: '100%', maxWidth: 420,
            backgroundColor: '#0a0a0a',
            borderRadius: 18,
            borderWidth: 1, borderColor: '#1f1f1f',
            padding: 20, gap: 12,
          }}>
            <View style={{
              flexDirection: 'row', alignItems: 'center',
              justifyContent: 'space-between', marginBottom: 4,
            }}>
              <Text style={{ color: '#ffffff', fontSize: 18, fontWeight: '800' }}>
                Link new device
              </Text>
              <Pressable
                onPress={() => !pairBusy && setPairOpen(false)}
                hitSlop={8}
              >
                <Ionicons name="close" size={22} color="#8b8b8b" />
              </Pressable>
            </View>

            <Text style={{ color: '#8b8b8b', fontSize: 12, lineHeight: 18 }}>
              Open the new device, tap <Text style={{ color: '#ffffff' }}>Pair</Text> on
              the welcome screen, then transcribe the code + device key shown there.
            </Text>

            <PairInput
              label="6-digit code"
              value={pairCode}
              onChangeText={setPairCode}
              placeholder="000000"
              keyboardType="number-pad"
              maxLength={6}
              monospace
            />
            <PairInput
              label="Device key"
              value={pairKey}
              onChangeText={setPairKey}
              placeholder="64 hex chars"
              autoCapitalize="none"
              maxLength={64}
              monospace
            />
            <PairInput
              label="Name for this device (optional)"
              value={pairName}
              onChangeText={setPairName}
              placeholder="e.g. Alice's laptop"
              maxLength={64}
            />

            <View style={{
              flexDirection: 'row', justifyContent: 'flex-end',
              gap: 10, marginTop: 8,
            }}>
              <Pressable
                onPress={() => setPairOpen(false)}
                disabled={pairBusy}
                style={({ pressed }) => ({
                  paddingHorizontal: 16, paddingVertical: 10,
                  borderRadius: 999,
                  backgroundColor: pressed ? '#1a1a1a' : 'transparent',
                  opacity: pairBusy ? 0.5 : 1,
                })}
              >
                <Text style={{ color: '#8b8b8b', fontSize: 14, fontWeight: '700' }}>
                  Cancel
                </Text>
              </Pressable>
              <Pressable
                onPress={submitPair}
                disabled={pairBusy}
                style={({ pressed }) => ({
                  paddingHorizontal: 18, paddingVertical: 10,
                  borderRadius: 999,
                  backgroundColor: pressed ? '#1580c8' : '#1d9bf0',
                  opacity: pairBusy ? 0.7 : 1,
                  minWidth: 90, alignItems: 'center',
                })}
              >
                {pairBusy ? (
                  <ActivityIndicator size="small" color="#ffffff" />
                ) : (
                  <Text style={{ color: '#ffffff', fontSize: 14, fontWeight: '700' }}>
                    Link
                  </Text>
                )}
              </Pressable>
            </View>
          </View>
        </KeyboardAvoidingView>
      </Modal>
    </View>
  );
}

function PairInput({
  label, value, onChangeText, placeholder, keyboardType, autoCapitalize,
  maxLength, monospace,
}: {
  label: string;
  value: string;
  onChangeText: (v: string) => void;
  placeholder?: string;
  keyboardType?: 'default' | 'number-pad';
  autoCapitalize?: 'none' | 'sentences';
  maxLength?: number;
  monospace?: boolean;
}) {
  return (
    <View>
      <Text style={{
        color: '#8b8b8b', fontSize: 11, fontWeight: '700',
        textTransform: 'uppercase', letterSpacing: 1, marginBottom: 6,
      }}>
        {label}
      </Text>
      <TextInput
        value={value}
        onChangeText={onChangeText}
        placeholder={placeholder}
        placeholderTextColor="#3a3a3a"
        keyboardType={keyboardType}
        autoCapitalize={autoCapitalize ?? 'sentences'}
        autoCorrect={false}
        maxLength={maxLength}
        style={{
          color: '#ffffff', fontSize: monospace ? 13 : 14,
          fontFamily: monospace ? 'monospace' : undefined,
          backgroundColor: '#000000',
          borderRadius: 10,
          paddingHorizontal: 12, paddingVertical: 10,
          borderWidth: 1, borderColor: '#1f1f1f',
        }}
      />
    </View>
  );
}
