import React, {useState, useEffect, useRef, useCallback} from 'react';
import {
  StyleSheet,
  View,
  Text,
  TouchableOpacity,
  FlatList,
  ScrollView,
  Platform,
  PermissionsAndroid,
  DeviceEventEmitter,
  NativeEventEmitter,
  NativeModules,
  ActivityIndicator,
} from 'react-native';
import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';
import AsyncStorage from '@react-native-async-storage/async-storage';

// ── Native module types ──────────────────────────────────────────────

const DEVICE_TYPE_KEYS = [
  'AM3S', 'AM4', 'PO3', 'BP5', 'BP5S', 'BP3L', 'BP7', 'BP7S',
  'KN550', 'HS2', 'HS2S', 'HS4S', 'BG1', 'BG1S', 'BG5', 'BG5S',
  'ECG3', 'BTM', 'TS28B', 'NT13B',
] as const;

type DeviceTypeName = (typeof DEVICE_TYPE_KEYS)[number];
type DiscoveryConstant = string | number;

interface IHealthDeviceManager {
  AM3S: DiscoveryConstant; AM4: DiscoveryConstant; PO3: DiscoveryConstant;
  BP5: DiscoveryConstant; BP5S: DiscoveryConstant; BP3L: DiscoveryConstant;
  BP7: DiscoveryConstant; BP7S: DiscoveryConstant; KN550: DiscoveryConstant;
  HS2: DiscoveryConstant; HS2S: DiscoveryConstant; HS4S: DiscoveryConstant;
  BG1: DiscoveryConstant; BG1S: DiscoveryConstant; BG5: DiscoveryConstant;
  BG5S: DiscoveryConstant; ECG3: DiscoveryConstant; BTM: DiscoveryConstant;
  TS28B: DiscoveryConstant; NT13B: DiscoveryConstant;
  Event_Scan_Device: string;
  Event_Scan_Finish: string;
  Event_Device_Connected: string;
  Event_Device_Connect_Failed: string;
  Event_Device_Disconnect: string;
  Event_Authenticate_Result: string;
  startDiscovery(type: DeviceTypeName | string): void;
  stopDiscovery(): void;
  connectDevice(mac: string, type: string): void;
  disconnectDevice(mac: string, type: string): void;
  sdkAuthWithLicense(license: string): void;
  authenConfigureInfo(userName: string, clientID: string, clientSecret: string): void;
  getDevicesIDPS(mac: string, callback: (idps: Record<string, string>) => void): void;
}

interface IBP550BTModule {
  Event_Notify: string;
  getBattery(mac: string): void;
  getOffLineNum(mac: string): void;
  getOffLineData(mac: string): void;
  getFunctionInfo(mac: string): void;
  disconnect(mac: string): void;
  getAllConnectedDevices(): void;
}

interface IPO3Module {
  Event_Notify: string;
  getBattery(mac: string): void;
  startMeasure(mac: string): void;
  getHistoryData(mac: string): void;
  disconnect(mac: string): void;
}

interface IPT3SBTModule {
  Event_Notify: string;
  getBattery(mac: string): void;
  getHistoryData(mac: string): void;
  getHistoryCount(mac: string): void;
  setUnit(mac: string, unit: number): void;
  disconnect(mac: string): void;
}

interface IHS2SModule {
  Event_Notify: string;
  getBattery(mac: string): void;
  getMemoryDataCount(mac: string, id: number): void;
  getMemoryData(mac: string, id: number): void;
  getAnonymousMemoryData(mac: string): void;
  disconnect(mac: string): void;
}

interface IBG5SModule {
  Event_Notify: string;
  getStatusInfo(mac: string): void;
  getOfflineData(mac: string): void;
  startMeasure(mac: string, type: number): void;
  disConnect(mac: string): void;
}

const mgr = NativeModules.iHealthDeviceManagerModule as IHealthDeviceManager;
const bp550 = NativeModules.BP550BTModule as IBP550BTModule;
const po3 = NativeModules.PO3Module as IPO3Module;
const pt3sbt = NativeModules.PT3SBTModule as IPT3SBTModule;
const hs2s = NativeModules.HS2SModule as IHS2SModule;
const bg5s = NativeModules.BG5SModule as IBG5SModule;

// Device type → module mapping
const DEVICE_MODULES: Record<string, {module: {Event_Notify: string; disconnect: (mac: string) => void} | null; label: string}> = {
  KN550: {module: bp550, label: 'Blood Pressure'},
  'KN-550BT': {module: bp550, label: 'Blood Pressure'},
  PO3: {module: po3, label: 'Pulse Oximeter'},
  PT3SBT: {module: pt3sbt, label: 'Thermometer'},
  HS2S: {module: hs2s, label: 'Scale'},
  BG5S: {module: bg5s, label: 'Glucose Monitor'},
};

// ── Types ────────────────────────────────────────────────────────────

type Device = {mac: string; type: string; rssi?: number; timestamp: number};

type SavedDevice = {mac: string; type: string; addedAt: string};

type Reading = {
  mac: string;
  deviceType?: string;
  // BP
  sys?: number;
  dia?: number;
  pulse?: number;
  // SpO2
  spo2?: number;
  pulseRate?: number;
  // Temperature
  temperature?: number;
  tempUnit?: string;
  // Weight/Scale
  weight?: number;
  bodyFat?: number;
  bmi?: number;
  // Glucose
  glucose?: number;
  // Common
  battery?: number;
  date?: string;
  fetchedAt: string;
};

type Screen = 'home' | 'dashboard' | 'debug' | 'debug-device';

const STORAGE_KEY_DEVICES = '@ihealth/saved_devices';
const STORAGE_KEY_READINGS = '@ihealth/readings';

// ── Helpers ──────────────────────────────────────────────────────────

async function requestAndroidPermissions(): Promise<boolean> {
  if (Platform.OS !== 'android') return true;
  const perms: string[] = [];
  if (Platform.Version >= 31) {
    perms.push(
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
    );
  }
  perms.push(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
  const r = await PermissionsAndroid.requestMultiple(perms as any);
  return Object.values(r).every(v => v === PermissionsAndroid.RESULTS.GRANTED);
}

function getEmitter() {
  return Platform.OS === 'ios'
    ? new NativeEventEmitter(NativeModules.iHealthDeviceManagerModule)
    : DeviceEventEmitter;
}

function getBPEmitter() {
  return Platform.OS === 'ios'
    ? new NativeEventEmitter(NativeModules.BP550BTModule)
    : DeviceEventEmitter;
}

// ── Home Screen ──────────────────────────────────────────────────────

function HomeScreen({onNav}: {onNav: (s: Screen) => void}) {
  return (
    <SafeAreaView style={s.container}>
      <View style={s.homeCenter}>
        <Text style={s.homeTitle}>iHealth</Text>
        <Text style={s.homeSubtitle}>Blood Pressure Monitor</Text>

        <TouchableOpacity
          style={s.homeButton}
          onPress={() => onNav('dashboard')}>
          <Text style={s.homeButtonText}>Dashboard</Text>
          <Text style={s.homeButtonSub}>View your devices and readings</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[s.homeButton, s.homeButtonSecondary]}
          onPress={() => onNav('debug')}>
          <Text style={[s.homeButtonText, s.homeButtonTextSecondary]}>
            Debug Scanner
          </Text>
          <Text style={[s.homeButtonSub, s.homeButtonTextSecondary]}>
            Scan all devices, raw logs
          </Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
}

// ── Dashboard Screen ─────────────────────────────────────────────────

function DashboardScreen({onBack}: {onBack: () => void}) {
  const [savedDevices, setSavedDevices] = useState<SavedDevice[]>([]);
  const [readings, setReadings] = useState<Reading[]>([]);
  const [foundDevices, setFoundDevices] = useState<Device[]>([]);
  const [status, setStatus] = useState('Starting...');
  const foundRef = useRef<Device[]>([]);
  const savedRef = useRef<SavedDevice[]>([]);
  const readingsRef = useRef<Reading[]>([]);
  const syncingMac = useRef<string | null>(null);

  // Load saved data on mount
  useEffect(() => {
    (async () => {
      const [devJson, readJson] = await Promise.all([
        AsyncStorage.getItem(STORAGE_KEY_DEVICES),
        AsyncStorage.getItem(STORAGE_KEY_READINGS),
      ]);
      const devs: SavedDevice[] = devJson ? JSON.parse(devJson) : [];
      const reads: Reading[] = readJson ? JSON.parse(readJson) : [];
      setSavedDevices(devs);
      savedRef.current = devs;
      setReadings(reads);
      readingsRef.current = reads;
      await requestAndroidPermissions();
    })();
  }, []);

  // Always-on scan loop: restart scan every time it finishes
  useEffect(() => {
    const emitter = getEmitter();
    const bpEmitter = getBPEmitter();

    const startScan = () => {
      try { mgr.startDiscovery('ALL'); }
      catch (_) {}
      setStatus('Scanning...');
    };

    // When a device is found
    const scanSub = emitter.addListener(
      mgr.Event_Scan_Device ?? 'event_scan_device',
      (e: {mac: string; type: string; rssi?: number}) => {
        if (e.type === 'AM3') return;

        // Track all found devices
        const exists = foundRef.current.find(d => d.mac === e.mac);
        if (!exists) {
          const updated = [...foundRef.current, {mac: e.mac, type: e.type, rssi: e.rssi, timestamp: Date.now()}];
          foundRef.current = updated;
          setFoundDevices(updated);
        }

        // Auto-connect if it's a saved device we haven't synced yet
        const isSaved = savedRef.current.some(d => d.mac === e.mac);
        if (isSaved && !syncingMac.current) {
          syncingMac.current = e.mac;
          setStatus(`Found ${e.mac.slice(-4)}, connecting...`);
          try { mgr.stopDiscovery(); } catch (_) {}
          mgr.connectDevice(e.mac, e.type);
        }
      },
    );

    // When scan finishes, restart after a short delay
    const finSub = emitter.addListener(
      mgr.Event_Scan_Finish ?? 'event_scan_finish',
      () => {
        if (!syncingMac.current) {
          setTimeout(startScan, 3000);
        }
      },
    );

    // Helper: listen for a native event, resolve on match, timeout
    const awaitEvent = <T,>(
      eventEmitter: typeof DeviceEventEmitter,
      eventName: string,
      match: (ev: Record<string, unknown>) => T | undefined,
      timeoutMs = 5000,
    ): Promise<T | undefined> =>
      new Promise(resolve => {
        const sub = eventEmitter.addListener(eventName, (ev: Record<string, unknown>) => {
          const result = match(ev);
          if (result !== undefined) { sub.remove(); resolve(result); }
        });
        setTimeout(() => { sub.remove(); resolve(undefined); }, timeoutMs);
      });

    // Helper: collect events into array until done signal
    const collectEvents = (
      eventEmitter: typeof DeviceEventEmitter,
      eventName: string,
      collect: (ev: Record<string, unknown>, results: Record<string, unknown>[]) => boolean, // return true when done
      timeoutMs = 10000,
    ): Promise<Record<string, unknown>[]> =>
      new Promise(resolve => {
        const results: Record<string, unknown>[] = [];
        const sub = eventEmitter.addListener(eventName, (ev: Record<string, unknown>) => {
          if (collect(ev, results)) { sub.remove(); resolve(results); }
        });
        setTimeout(() => { sub.remove(); resolve(results); }, timeoutMs);
      });

    // ── Per-device sync logic ──
    const syncBP550 = async (mac: string): Promise<Reading[]> => {
      const notify = bp550?.Event_Notify ?? 'event_notify';
      const bpEm = getBPEmitter();
      // Start listening BEFORE calling native method
      const batteryPromise = awaitEvent<number>(bpEm, notify,
        ev => ev.action === 'battery_bp' && ev.battery != null ? ev.battery as number : undefined);
      bp550.getBattery(mac);
      const battery = await batteryPromise;

      const dataPromise = collectEvents(bpEm, notify, (ev, res) => {
        if (ev.action === 'historicaldata_bp' && ev.data)
          res.push(...(ev.data as Record<string, unknown>[]));
        return ev.action === 'get_historical_over_bp' || (ev.action === 'offlinenum' && ev.offlinenum === 0);
      });
      bp550.getOffLineData(mac);
      const data = await dataPromise;

      const readings: Reading[] = data.map(d => ({
        mac, deviceType: 'BP', sys: d.sys as number, dia: d.dia as number,
        pulse: d.heartRate as number, date: d.date as string,
        battery, fetchedAt: new Date().toISOString(),
      }));
      if (readings.length === 0 && battery != null)
        readings.push({mac, deviceType: 'BP', battery, fetchedAt: new Date().toISOString()});
      try { bp550.disconnect(mac); } catch (_) {}
      return readings;
    };

    const syncPO3 = async (mac: string): Promise<Reading[]> => {
      const notify = po3?.Event_Notify ?? 'event_notify';
      const em = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.PO3Module) : DeviceEventEmitter;
      const bp = awaitEvent<number>(em, notify,
        ev => ev.action === 'battery_po' && ev.battery != null ? ev.battery as number : undefined);
      po3.getBattery(mac);
      const battery = await bp;

      const dp = collectEvents(em, notify, (ev, res) => {
        if (ev.action === 'offlineData_po' && ev.offlinedata) {
          const arr = Array.isArray(ev.offlinedata) ? ev.offlinedata : [ev.offlinedata];
          res.push(...(arr as Record<string, unknown>[]));
        }
        return ev.action === 'offlineData_po' || ev.action === 'noOfflineData_po';
      });
      po3.getHistoryData(mac);
      const data = await dp;

      const readings: Reading[] = data.map(d => ({
        mac, deviceType: 'SpO2', spo2: d.bloodoxygen as number,
        pulseRate: d.heartrate as number, date: d.measuredate as string,
        battery, fetchedAt: new Date().toISOString(),
      }));
      if (readings.length === 0 && battery != null)
        readings.push({mac, deviceType: 'SpO2', battery, fetchedAt: new Date().toISOString()});
      try { po3.disconnect(mac); } catch (_) {}
      return readings;
    };

    const syncPT3SBT = async (mac: string): Promise<Reading[]> => {
      const notify = pt3sbt?.Event_Notify ?? 'event_notify';
      const em = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.PT3SBTModule) : DeviceEventEmitter;
      const bp = awaitEvent<number>(em, notify,
        ev => ev.action === 'action_get_battery' && ev.battery != null ? ev.battery as number : undefined);
      pt3sbt.getBattery(mac);
      const battery = await bp;

      const dp = collectEvents(em, notify, (ev, res) => {
        if (ev.action === 'action_get_history_data' && ev.history) {
          const arr = Array.isArray(ev.history) ? ev.history : [ev.history];
          res.push(...(arr as Record<string, unknown>[]));
          return true;
        }
        return false;
      });
      pt3sbt.getHistoryData(mac);
      const data = await dp;

      const readings: Reading[] = data.map(d => ({
        mac, deviceType: 'Temp', temperature: d.Tbody as number,
        date: d.ts as string, battery, fetchedAt: new Date().toISOString(),
      }));
      if (readings.length === 0 && battery != null)
        readings.push({mac, deviceType: 'Temp', battery, fetchedAt: new Date().toISOString()});
      try { pt3sbt.disconnect(mac); } catch (_) {}
      return readings;
    };

    const syncHS2S = async (mac: string): Promise<Reading[]> => {
      const notify = hs2s?.Event_Notify ?? 'event_notify';
      const em = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.HS2SModule) : DeviceEventEmitter;
      const bp = awaitEvent<number>(em, notify,
        ev => ev.action === 'battery_hs' && ev.battery != null ? ev.battery as number : undefined);
      hs2s.getBattery(mac);
      const battery = await bp;

      const dp = collectEvents(em, notify, (ev, res) => {
        if (ev.action === 'action_history_data' && ev.weight != null) {
          res.push(ev);
        }
        return ev.action === 'action_anonymous_data_num' || ev.action === 'action_anonymous_data';
      });
      hs2s.getAnonymousMemoryData(mac);
      const data = await dp;

      const readings: Reading[] = data.map(d => ({
        mac, deviceType: 'Scale', weight: d.weight as number,
        bodyFat: d.body_fit_percentage as number,
        bmi: d.body_mass_index as number,
        date: d.data_measure_time as string,
        battery, fetchedAt: new Date().toISOString(),
      }));
      if (readings.length === 0 && battery != null)
        readings.push({mac, deviceType: 'Scale', battery, fetchedAt: new Date().toISOString()});
      try { hs2s.disconnect(mac); } catch (_) {}
      return readings;
    };

    const syncBG5S = async (mac: string): Promise<Reading[]> => {
      const notify = bg5s?.Event_Notify ?? 'event_notify';
      const em = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.BG5SModule) : DeviceEventEmitter;

      const dp = collectEvents(em, notify, (ev, res) => {
        if (ev.action === 'action_get_offline_data' && ev.offline_data) {
          const arr = Array.isArray(ev.offline_data) ? ev.offline_data : [ev.offline_data];
          res.push(...(arr as Record<string, unknown>[]));
          return true;
        }
        if (ev.action === 'action_get_status_info' && ev.info_offline_data_num === 0) return true;
        return false;
      });
      bg5s.getOfflineData(mac);
      const data = await dp;

      const readings: Reading[] = data.map(d => ({
        mac, deviceType: 'Glucose', glucose: d.data_value as number,
        date: d.data_measure_time as string,
        fetchedAt: new Date().toISOString(),
      }));
      try { bg5s.disConnect(mac); } catch (_) {}
      return readings;
    };

    // When connected, pull data based on device type
    const connSub = emitter.addListener(
      mgr.Event_Device_Connected ?? 'event_device_connected',
      async (e: {mac: string; type: string}) => {
        if (e.mac !== syncingMac.current) return;
        setStatus(`Connected to ${e.mac.slice(-4)}, reading...`);

        let newReadings: Reading[] = [];
        try {
          switch (e.type) {
            case 'KN550': case 'KN-550BT': newReadings = await syncBP550(e.mac); break;
            case 'PO3': newReadings = await syncPO3(e.mac); break;
            case 'PT3SBT': newReadings = await syncPT3SBT(e.mac); break;
            case 'HS2S': newReadings = await syncHS2S(e.mac); break;
            case 'BG5S': newReadings = await syncBG5S(e.mac); break;
            default:
              // Unknown device — just disconnect
              try { mgr.disconnectDevice(e.mac, e.type); } catch (_) {}
          }
        } catch (err) {
          console.log('Sync error:', err);
        }

        if (newReadings.length > 0) {
          const all = [...readingsRef.current, ...newReadings];
          readingsRef.current = all;
          setReadings(all);
          await AsyncStorage.setItem(STORAGE_KEY_READINGS, JSON.stringify(all));
        }

        setStatus(`Synced ${e.mac.slice(-4)} (${newReadings.length} readings)`);
        syncingMac.current = null;
        setTimeout(startScan, 3000);
      },
    );

    const failSub = emitter.addListener(
      mgr.Event_Device_Connect_Failed ?? 'event_device_connect_failed',
      () => {
        setStatus('Connect failed, resuming scan...');
        syncingMac.current = null;
        setTimeout(startScan, 3000);
      },
    );

    const dcSub = emitter.addListener(
      mgr.Event_Device_Disconnect ?? 'event_device_disconnect',
      () => {
        if (syncingMac.current) {
          syncingMac.current = null;
          setTimeout(startScan, 3000);
        }
      },
    );

    // Start first scan
    startScan();

    return () => {
      scanSub.remove(); finSub.remove(); connSub.remove();
      failSub.remove(); dcSub.remove();
      try { mgr.stopDiscovery(); } catch (_) {}
    };
  }, []);

  const addDevice = async (dev: Device) => {
    const newDev: SavedDevice = {mac: dev.mac, type: dev.type, addedAt: new Date().toISOString()};
    const updated = [...savedRef.current, newDev];
    savedRef.current = updated;
    setSavedDevices(updated);
    await AsyncStorage.setItem(STORAGE_KEY_DEVICES, JSON.stringify(updated));
    const f = foundRef.current.filter(d => d.mac !== dev.mac);
    foundRef.current = f;
    setFoundDevices(f);
  };

  const removeDevice = async (mac: string) => {
    const updated = savedRef.current.filter(d => d.mac !== mac);
    savedRef.current = updated;
    setSavedDevices(updated);
    await AsyncStorage.setItem(STORAGE_KEY_DEVICES, JSON.stringify(updated));
  };

  const isDeviceSaved = (mac: string) => savedRef.current.some(d => d.mac === mac);

  const recentReadings = readings
    .filter(r => r.sys != null || r.spo2 != null || r.temperature != null || r.weight != null || r.glucose != null)
    .slice(-30)
    .reverse();

  return (
    <SafeAreaView style={s.container}>
      <TouchableOpacity style={s.backButton} onPress={onBack}>
        <Text style={s.backText}>Home</Text>
      </TouchableOpacity>

      <Text style={s.title}>Dashboard 🦄✨</Text>

      {/* Show status only when actively syncing a device */}
      {status.includes('connecting') || status.includes('reading') || status.includes('Synced') ? (
        <View style={s.syncBar}>
          <ActivityIndicator size="small" color="#2196F3" />
          <Text style={s.syncText}>{status}</Text>
        </View>
      ) : null}

      {/* All devices — unified list, saved ones marked */}
      <Text style={s.sectionTitle}>
        Devices ({foundDevices.length} nearby, {savedDevices.length} saved)
      </Text>

      {/* Merge: all found devices + saved devices not currently found */}
      {(() => {
        const allMacs = new Set([
          ...foundDevices.map(d => d.mac),
          ...savedDevices.map(d => d.mac),
        ]);
        const merged = Array.from(allMacs).map(mac => {
          const found = foundDevices.find(d => d.mac === mac);
          const saved = savedDevices.find(d => d.mac === mac);
          return {
            mac,
            type: found?.type ?? saved?.type ?? 'KN550',
            rssi: found?.rssi,
            nearby: !!found,
            saved: !!saved,
          };
        });
        // Sort: saved first, then nearby, then rest
        merged.sort((a, b) => {
          if (a.saved !== b.saved) return a.saved ? -1 : 1;
          if (a.nearby !== b.nearby) return a.nearby ? -1 : 1;
          return 0;
        });
        return merged.map(d => (
          <View key={d.mac} style={s.savedRow}>
            <View style={[s.deviceIcon, d.saved && s.deviceIconSaved, !d.nearby && s.deviceOffline]}>
              <Text style={s.deviceIconText}>{d.type.substring(0, 3)}</Text>
            </View>
            <View style={[s.deviceInfo, !d.nearby && s.deviceOffline]}>
              <Text style={s.deviceType}>
                {d.type}
                {d.saved ? ' ' : ''}
                {d.saved && <Text style={s.savedBadge}>SAVED</Text>}
              </Text>
              <Text style={s.deviceMac}>
                {d.mac}
                {!d.nearby ? '  (offline)' : d.rssi != null ? `  ${d.rssi} dBm` : ''}
              </Text>
            </View>
            {d.saved ? (
              <TouchableOpacity onPress={() => removeDevice(d.mac)}>
                <Text style={s.removeText}>Remove</Text>
              </TouchableOpacity>
            ) : (
              <TouchableOpacity style={s.addButton} onPress={() => addDevice({mac: d.mac, type: d.type, timestamp: Date.now()})}>
                <Text style={s.addButtonText}>Save</Text>
              </TouchableOpacity>
            )}
          </View>
        ));
      })()}

      {/* Readings */}
      <Text style={[s.sectionTitle, {marginTop: 16}]}>
        Readings ({recentReadings.length})
      </Text>
      <FlatList
        data={recentReadings}
        keyExtractor={(_, i) => String(i)}
        style={s.list}
        renderItem={({item}) => (
          <View style={s.readingRow}>
            {item.sys != null && (
              <View style={s.readingValues}>
                <Text style={s.readingSys}>{item.sys}</Text>
                <Text style={s.readingSlash}>/</Text>
                <Text style={s.readingDia}>{item.dia ?? '--'}</Text>
                <Text style={s.readingUnit}>mmHg</Text>
                <Text style={s.readingPulse}>{item.pulse ?? '--'} bpm</Text>
              </View>
            )}
            {item.spo2 != null && (
              <View style={s.readingValues}>
                <Text style={s.readingSys}>{item.spo2}%</Text>
                <Text style={s.readingUnit}>SpO2</Text>
                <Text style={s.readingPulse}>{item.pulseRate ?? '--'} bpm</Text>
              </View>
            )}
            {item.temperature != null && (
              <View style={s.readingValues}>
                <Text style={s.readingSys}>{item.temperature}</Text>
                <Text style={s.readingUnit}>{item.tempUnit ?? 'C'}</Text>
              </View>
            )}
            {item.weight != null && (
              <View style={s.readingValues}>
                <Text style={s.readingSys}>{item.weight}</Text>
                <Text style={s.readingUnit}>kg</Text>
                {item.bodyFat != null && <Text style={s.readingPulse}>{item.bodyFat}% fat</Text>}
                {item.bmi != null && <Text style={s.readingPulse}>BMI {item.bmi}</Text>}
              </View>
            )}
            {item.glucose != null && (
              <View style={s.readingValues}>
                <Text style={s.readingSys}>{item.glucose}</Text>
                <Text style={s.readingUnit}>mg/dL</Text>
              </View>
            )}
            <View style={s.readingMeta}>
              <Text style={s.readingDate}>
                {item.deviceType ? `${item.deviceType}  ` : ''}
                {item.date ?? item.fetchedAt.split('T')[0]}
              </Text>
              <Text style={s.readingMac}>{item.mac}</Text>
            </View>
          </View>
        )}
        ListEmptyComponent={
          <Text style={s.emptyText}>
            {savedDevices.length === 0
              ? 'Add a device to start tracking'
              : 'No readings yet. Sync to pull data.'}
          </Text>
        }
      />
    </SafeAreaView>
  );
}

// ── Debug Scanner Screen ─────────────────────────────────────────────

function DebugScannerScreen({
  onBack,
  onSelectDevice,
}: {
  onBack: () => void;
  onSelectDevice: (d: Device) => void;
}) {
  const [devices, setDevices] = useState<Device[]>([]);
  const [scanning, setScanning] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const devicesRef = useRef<Device[]>([]);

  useEffect(() => {
    if (!mgr) { setError('iHealth native module not found.'); return; }
    const emitter = getEmitter();
    const sub = emitter.addListener(
      mgr.Event_Scan_Device ?? 'event_scan_device',
      (e: {mac: string; type: string; rssi?: number}) => {
        if (e.type === 'AM3') return;
        const {mac = '', type = 'Unknown', rssi} = e;
        const idx = devicesRef.current.findIndex(d => d.mac === mac);
        let updated: Device[];
        if (idx >= 0) {
          updated = [...devicesRef.current];
          updated[idx] = {mac, type, rssi, timestamp: Date.now()};
        } else {
          updated = [...devicesRef.current, {mac, type, rssi, timestamp: Date.now()}];
        }
        devicesRef.current = updated;
        setDevices(updated);
      },
    );
    const finSub = emitter.addListener(
      mgr.Event_Scan_Finish ?? 'event_scan_finish',
      () => setScanning(false),
    );
    return () => { sub.remove(); finSub.remove(); };
  }, []);

  const startScan = async () => {
    setError(null);
    const ok = await requestAndroidPermissions();
    if (!ok) { setError('Permissions denied'); return; }
    devicesRef.current = [];
    setDevices([]);
    setScanning(true);
    if (Platform.OS === 'android') {
      try { mgr.startDiscovery('ALL'); } catch (e) { console.log(e); }
    } else {
      const types = ['KN550', 'BP3L', 'BP5S', 'BP7S', 'AM3S', 'AM4',
        'PO3', 'HS2', 'HS2S', 'HS4S', 'BG5S', 'BG1S', 'PO1', 'ECG3'];
      let i = 0;
      const next = () => {
        if (i < types.length) {
          try { mgr.startDiscovery(types[i]); } catch (_) {}
          i++;
          setTimeout(next, 2000);
        }
      };
      setTimeout(next, 2000);
    }
  };

  const stopScan = () => {
    try { mgr.stopDiscovery(); } catch (_) {}
    setScanning(false);
  };

  return (
    <SafeAreaView style={s.container}>
      <TouchableOpacity style={s.backButton} onPress={onBack}>
        <Text style={s.backText}>Home</Text>
      </TouchableOpacity>
      <Text style={s.title}>Debug Scanner</Text>
      <Text style={s.subtitle}>
        {scanning ? `Scanning... (${devices.length})` : `${devices.length} device(s)`}
      </Text>
      {error && <Text style={s.error}>{error}</Text>}
      <TouchableOpacity
        style={[s.button, scanning && s.buttonStop]}
        onPress={scanning ? stopScan : startScan}>
        <Text style={s.buttonText}>{scanning ? 'Stop' : 'Start Scan'}</Text>
      </TouchableOpacity>
      <FlatList
        data={devices}
        keyExtractor={item => item.mac}
        renderItem={({item}) => (
          <TouchableOpacity style={s.deviceRow} onPress={() => { stopScan(); onSelectDevice(item); }}>
            <View style={s.deviceIcon}>
              <Text style={s.deviceIconText}>{item.type.substring(0, 3)}</Text>
            </View>
            <View style={s.deviceInfo}>
              <Text style={s.deviceType}>{item.type}</Text>
              <Text style={s.deviceMac}>{item.mac}</Text>
            </View>
            {item.rssi != null && <Text style={s.deviceRssi}>{item.rssi} dBm</Text>}
            <Text style={s.chevron}>{'>'}</Text>
          </TouchableOpacity>
        )}
        style={s.list}
        contentContainerStyle={devices.length === 0 && s.emptyList}
        ListEmptyComponent={
          <Text style={s.emptyText}>
            {scanning ? 'Scanning...' : 'Tap Start Scan'}
          </Text>
        }
      />
    </SafeAreaView>
  );
}

// ── Debug Device Screen ──────────────────────────────────────────────

function DebugDeviceScreen({device, onBack}: {device: Device; onBack: () => void}) {
  const [connected, setConnected] = useState(false);
  const [connecting, setConnecting] = useState(false);
  const [log, setLog] = useState<string[]>([]);

  const addLog = (msg: string) =>
    setLog(prev => [`[${new Date().toLocaleTimeString()}] ${msg}`, ...prev]);

  useEffect(() => {
    const emitter = getEmitter();
    const bpEmitter = getBPEmitter();
    const connSub = emitter.addListener(
      mgr.Event_Device_Connected ?? 'event_device_connected',
      (e: {mac: string}) => {
        if (e.mac === device.mac) { setConnected(true); setConnecting(false); addLog('Connected'); }
      },
    );
    const failSub = emitter.addListener(
      mgr.Event_Device_Connect_Failed ?? 'event_device_connect_failed',
      (e: {mac: string; errorid?: number}) => {
        if (e.mac === device.mac) { setConnecting(false); addLog(`Connect failed: ${e.errorid}`); }
      },
    );
    const dcSub = emitter.addListener(
      mgr.Event_Device_Disconnect ?? 'event_device_disconnect',
      (e: {mac: string}) => {
        if (e.mac === device.mac) { setConnected(false); addLog('Disconnected'); }
      },
    );
    const notSub = bpEmitter.addListener(
      bp550?.Event_Notify ?? 'event_notify',
      (e: Record<string, unknown>) => addLog(JSON.stringify(e, null, 2)),
    );
    return () => { connSub.remove(); failSub.remove(); dcSub.remove(); notSub.remove(); };
  }, [device.mac]);

  const actions = [
    {label: 'Get Battery', fn: () => { addLog('Battery...'); bp550.getBattery(device.mac); }},
    {label: 'Function Info', fn: () => { addLog('FuncInfo...'); bp550.getFunctionInfo(device.mac); }},
    {label: 'Offline Count', fn: () => { addLog('OfflineNum...'); bp550.getOffLineNum(device.mac); }},
    {label: 'Offline Data', fn: () => { addLog('OfflineData...'); bp550.getOffLineData(device.mac); }},
    {label: 'IDPS', fn: () => {
      addLog('IDPS...');
      mgr.getDevicesIDPS(device.mac, idps => addLog(JSON.stringify(idps, null, 2)));
    }},
  ];

  return (
    <SafeAreaView style={s.container}>
      <TouchableOpacity style={s.backButton} onPress={onBack}>
        <Text style={s.backText}>Back</Text>
      </TouchableOpacity>
      <Text style={s.title}>{device.type}</Text>
      <Text style={s.deviceMac}>{device.mac}</Text>
      <Text style={[s.statusBadge, connected && s.statusConnected]}>
        {connecting ? 'Connecting...' : connected ? 'Connected' : 'Disconnected'}
      </Text>
      {!connected && !connecting && (
        <TouchableOpacity style={s.button} onPress={() => {
          setConnecting(true); addLog('Connecting...');
          mgr.connectDevice(device.mac, device.type);
        }}>
          <Text style={s.buttonText}>Connect</Text>
        </TouchableOpacity>
      )}
      {connected && (
        <TouchableOpacity style={[s.button, s.buttonStop]} onPress={() => {
          addLog('Disconnecting...'); bp550.disconnect(device.mac);
        }}>
          <Text style={s.buttonText}>Disconnect</Text>
        </TouchableOpacity>
      )}
      <ScrollView horizontal showsHorizontalScrollIndicator={false} style={s.actionsRow}>
        {actions.map(a => (
          <TouchableOpacity
            key={a.label}
            style={[s.actionButton, !connected && s.actionDisabled]}
            disabled={!connected}
            onPress={a.fn}>
            <Text style={[s.actionText, !connected && s.actionTextDisabled]}>{a.label}</Text>
          </TouchableOpacity>
        ))}
      </ScrollView>
      <Text style={s.sectionTitle}>Log</Text>
      <FlatList
        data={log}
        keyExtractor={(_, i) => String(i)}
        renderItem={({item}) => <Text style={s.logLine}>{item}</Text>}
        style={s.logList}
      />
    </SafeAreaView>
  );
}

// ── App Root ─────────────────────────────────────────────────────────

function App() {
  const [screen, setScreen] = useState<Screen>('home');
  const [debugDevice, setDebugDevice] = useState<Device | null>(null);

  return (
    <SafeAreaProvider>
      {screen === 'home' && <HomeScreen onNav={setScreen} />}
      {screen === 'dashboard' && (
        <DashboardScreen onBack={() => setScreen('home')} />
      )}
      {screen === 'debug' && (
        <DebugScannerScreen
          onBack={() => setScreen('home')}
          onSelectDevice={d => { setDebugDevice(d); setScreen('debug-device'); }}
        />
      )}
      {screen === 'debug-device' && debugDevice && (
        <DebugDeviceScreen
          device={debugDevice}
          onBack={() => setScreen('debug')}
        />
      )}
    </SafeAreaProvider>
  );
}

// ── Styles ───────────────────────────────────────────────────────────

const s = StyleSheet.create({
  container: {flex: 1, backgroundColor: '#f5f5f5', paddingHorizontal: 16},
  // Home
  homeCenter: {flex: 1, justifyContent: 'center'},
  homeTitle: {fontSize: 36, fontWeight: '800', color: '#1a1a1a', textAlign: 'center'},
  homeSubtitle: {fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 40},
  homeButton: {
    backgroundColor: '#2196F3', padding: 20, borderRadius: 14,
    marginBottom: 12, alignItems: 'center',
  },
  homeButtonSecondary: {backgroundColor: '#fff', borderWidth: 1, borderColor: '#ddd'},
  homeButtonText: {color: '#fff', fontSize: 18, fontWeight: '700'},
  homeButtonTextSecondary: {color: '#333'},
  homeButtonSub: {color: 'rgba(255,255,255,0.8)', fontSize: 13, marginTop: 4},
  // Common
  title: {fontSize: 28, fontWeight: '700', color: '#1a1a1a', marginTop: 16},
  subtitle: {fontSize: 14, color: '#666', marginTop: 4, marginBottom: 16},
  sectionTitle: {fontSize: 16, fontWeight: '600', color: '#333', marginTop: 8, marginBottom: 8},
  error: {color: '#d32f2f', fontSize: 13, marginBottom: 8, backgroundColor: '#ffebee', padding: 8, borderRadius: 6},
  button: {backgroundColor: '#2196F3', paddingVertical: 14, borderRadius: 10, alignItems: 'center', marginBottom: 12},
  buttonStop: {backgroundColor: '#f44336'},
  buttonText: {color: '#fff', fontSize: 16, fontWeight: '600'},
  buttonOutline: {backgroundColor: 'transparent', borderWidth: 1.5, borderColor: '#2196F3'},
  buttonTextOutline: {color: '#2196F3'},
  list: {flex: 1},
  emptyList: {flex: 1, justifyContent: 'center', alignItems: 'center'},
  emptyText: {color: '#999', fontSize: 15, textAlign: 'center'},
  backButton: {marginTop: 12, marginBottom: 4},
  backText: {color: '#2196F3', fontSize: 16},
  chevron: {fontSize: 18, color: '#ccc', marginLeft: 8},
  // Device rows
  deviceRow: {
    flexDirection: 'row', alignItems: 'center', backgroundColor: '#fff',
    padding: 14, borderRadius: 10, marginBottom: 8,
    shadowColor: '#000', shadowOffset: {width: 0, height: 1}, shadowOpacity: 0.05, shadowRadius: 2, elevation: 1,
  },
  deviceIcon: {
    width: 44, height: 44, borderRadius: 22, backgroundColor: '#e3f2fd',
    justifyContent: 'center', alignItems: 'center', marginRight: 12,
  },
  deviceIconText: {fontSize: 12, fontWeight: '700', color: '#1565c0'},
  deviceInfo: {flex: 1},
  deviceType: {fontSize: 16, fontWeight: '600', color: '#1a1a1a'},
  deviceMac: {fontSize: 12, color: '#888', marginTop: 2, fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace'},
  deviceRssi: {fontSize: 12, color: '#999', marginLeft: 8},
  // Dashboard
  savedRow: {
    flexDirection: 'row', alignItems: 'center', backgroundColor: '#fff',
    padding: 14, borderRadius: 10, marginBottom: 8, elevation: 1,
  },
  removeText: {color: '#f44336', fontSize: 13, fontWeight: '600'},
  deviceOffline: {opacity: 0.5},
  deviceIconSaved: {backgroundColor: '#c8e6c9'},
  savedBadge: {fontSize: 10, color: '#4caf50', fontWeight: '700'},
  foundRow: {
    flexDirection: 'row', alignItems: 'center', backgroundColor: '#e8f5e9',
    padding: 14, borderRadius: 10, marginBottom: 8,
  },
  addButton: {backgroundColor: '#4caf50', paddingVertical: 8, paddingHorizontal: 16, borderRadius: 8},
  addButtonText: {color: '#fff', fontSize: 14, fontWeight: '600'},
  syncBar: {flexDirection: 'row', alignItems: 'center', padding: 10, backgroundColor: '#e3f2fd', borderRadius: 8, marginBottom: 8},
  syncText: {color: '#1565c0', fontSize: 13, marginLeft: 8},
  syncDone: {color: '#4caf50', fontSize: 13, marginBottom: 8, fontWeight: '600'},
  scanningRow: {flexDirection: 'row', alignItems: 'center', padding: 12},
  scanningText: {color: '#666', fontSize: 13, marginLeft: 8},
  // Readings
  readingRow: {
    backgroundColor: '#fff', padding: 14, borderRadius: 10, marginBottom: 8, elevation: 1,
  },
  readingValues: {flexDirection: 'row', alignItems: 'baseline'},
  readingSys: {fontSize: 28, fontWeight: '700', color: '#1a1a1a'},
  readingSlash: {fontSize: 20, color: '#999', marginHorizontal: 4},
  readingDia: {fontSize: 28, fontWeight: '700', color: '#1a1a1a'},
  readingUnit: {fontSize: 12, color: '#999', marginLeft: 6},
  readingPulse: {fontSize: 14, color: '#666', marginLeft: 16},
  readingMeta: {flexDirection: 'row', justifyContent: 'space-between', marginTop: 4},
  readingDate: {fontSize: 12, color: '#999'},
  readingMac: {fontSize: 10, color: '#bbb', fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace'},
  // Debug device
  statusBadge: {fontSize: 13, color: '#f44336', marginTop: 8, marginBottom: 16, fontWeight: '600'},
  statusConnected: {color: '#4caf50'},
  actionsRow: {flexGrow: 0, marginBottom: 12},
  actionButton: {backgroundColor: '#e3f2fd', paddingVertical: 10, paddingHorizontal: 16, borderRadius: 8, marginRight: 8},
  actionDisabled: {backgroundColor: '#eee'},
  actionText: {color: '#1565c0', fontSize: 13, fontWeight: '600'},
  actionTextDisabled: {color: '#bbb'},
  logList: {flex: 1, marginTop: 4},
  logLine: {fontSize: 11, color: '#555', paddingVertical: 3, fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace'},
});

export default App;
