import React, { useState } from 'react';
import {
  View,
  Text,
  StyleSheet,
  Alert,
  ActivityIndicator,
  Modal,
  TouchableOpacity,
  ScrollView,
} from 'react-native';
import * as FileSystem from 'expo-file-system';
import * as Sharing from 'expo-sharing';
import * as DocumentPicker from 'expo-document-picker';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useUsers } from '@/contexts/UserContext';
import Button from '@/components/Button';
import { AntDesign } from '@expo/vector-icons';

// ── Helpers Map ────────────────────────────────────────────────────
const mapToObj = (m: any): Record<string, any> => {
  if (!m || !(m instanceof Map)) return m ?? {};
  const obj: Record<string, any> = {};
  for (const [k, v] of m.entries()) obj[String(k)] = v;
  return obj;
};

const objToMap = (obj: any): Map<number, any> => {
  if (!obj) return new Map();
  if (obj instanceof Map) return obj;
  return new Map(Object.entries(obj).map(([k, v]) => [Number(k), v]));
};

// ── Types ──────────────────────────────────────────────────────────
type Props = {
  visible: boolean;
  onClose: () => void;
};

type TransferStatus = 'idle' | 'exporting' | 'importing' | 'success' | 'error';

// ── Composant ──────────────────────────────────────────────────────
export const DataTransferPopup: React.FC<Props> = ({ visible, onClose }) => {
  const { currentUser, updateCurrentUserAsync, getBilanKey } = useUsers();
  const [status, setStatus] = useState<TransferStatus>('idle');
  const [statusMsg, setStatusMsg] = useState('');
  const [successMsg, setSuccessMsg] = useState('');

  const setMsg = (s: TransferStatus, msg: string) => {
    setStatus(s);
    setStatusMsg(msg);
  };

  // ── EXPORT ──────────────────────────────────────────────────────
  const handleExport = async () => {
    if (!currentUser) {
      Alert.alert('Erreur', 'Aucun utilisateur connecté.');
      return;
    }

    setMsg('exporting', 'Lecture des données…');

    try {
      // 1. Bilan principal (clé dynamique selon le rôle)
      const bilanKey = getBilanKey(currentUser.username);
      const bilanRaw = await AsyncStorage.getItem(bilanKey);
      const bilanData = bilanRaw ? JSON.parse(bilanRaw) : [];

      // 2. Toutes les clés de bilans possibles (multi-rôle)
      const allKeys = await AsyncStorage.getAllKeys();
      const allBilanKeys = allKeys.filter(k =>
        k.startsWith(`bilan_${currentUser.username}_`)
      );
      const allBilanEntries: Record<string, any[]> = {};
      for (const k of allBilanKeys) {
        const raw = await AsyncStorage.getItem(k);
        if (raw) allBilanEntries[k] = JSON.parse(raw);
      }

      // 3. Valeurs slider sauvegardées par symptôme
      const symptomKeys = allKeys.filter(k =>
        k.startsWith(`@symptom:lastValue:${currentUser.username}:`)
      );
      const symptomPairs = await AsyncStorage.multiGet(symptomKeys);
      const symptomValues: Record<string, any> = {};
      for (const [k, v] of symptomPairs) {
        if (v) symptomValues[k] = JSON.parse(v);
      }

      // 4. Construction du paquet
      setMsg('exporting', 'Génération du fichier…');
      const pkg = {
        version: 2,
        exportDate: new Date().toISOString(),
        username: currentUser.username,
        // User sérialisé (Map → objet plain)
        user: { ...currentUser, globalData: mapToObj(currentUser.globalData) },
        // Historique des bilans
        bilanMain: bilanData,
        bilanAllRoles: allBilanEntries,
        // Dernières valeurs slider
        symptomValues,
      };

      const json = JSON.stringify(pkg);
      const filename = `msdb_${currentUser.username}_${Date.now()}.msdb`;
      const filepath = FileSystem.cacheDirectory! + filename;

      await FileSystem.writeAsStringAsync(filepath, json, {
        encoding: FileSystem.EncodingType.UTF8,
      });

      setMsg('exporting', 'Ouverture du partage…');

      const canShare = await Sharing.isAvailableAsync();
      if (!canShare) {
        Alert.alert('Partage indisponible', 'Le partage natif n\'est pas disponible sur cet appareil.');
        setMsg('idle', '');
        return;
      }

      await Sharing.shareAsync(filepath, {
        mimeType: 'application/octet-stream',
        dialogTitle: 'Envoyer les données à l\'autre téléphone',
      });

      setMsg('idle', '');
    } catch (e: any) {
      Alert.alert('Erreur export', String(e?.message ?? e));
      setMsg('idle', '');
    }
  };

  // ── IMPORT ──────────────────────────────────────────────────────
  const handleImport = async () => {
    setMsg('importing', 'Sélection du fichier…');

    try {
      const result = await DocumentPicker.getDocumentAsync({
        type: ['application/octet-stream', '*/*'],
        copyToCacheDirectory: true,
      });

      if (result.canceled) {
        setMsg('idle', '');
        return;
      }

      setMsg('importing', 'Lecture du fichier…');
      const content = await FileSystem.readAsStringAsync(result.assets[0].uri, {
        encoding: FileSystem.EncodingType.UTF8,
      });

      let pkg: any;
      try {
        pkg = JSON.parse(content);
      } catch {
        Alert.alert('Fichier invalide', 'Le fichier sélectionné n\'est pas un fichier de transfert valide.');
        setMsg('idle', '');
        return;
      }

      if (!pkg.version || !pkg.user || !pkg.username) {
        Alert.alert('Fichier invalide', 'Format non reconnu. Assurez-vous d\'utiliser un fichier .msdb exporté depuis cette application.');
        setMsg('idle', '');
        return;
      }

      // Confirmation avant d'écraser
      Alert.alert(
        'Confirmer l\'import',
        `Importer les données de "${pkg.username}" exportées le ${new Date(pkg.exportDate).toLocaleString('fr-FR')} ?\n\nLes données actuelles de cet utilisateur seront remplacées.`,
        [
          {
            text: 'Annuler',
            style: 'cancel',
            onPress: () => setMsg('idle', ''),
          },
          {
            text: 'Importer',
            style: 'destructive',
            onPress: () => doImport(pkg),
          },
        ]
      );
    } catch (e: any) {
      Alert.alert('Erreur', `Impossible d\'ouvrir le fichier : ${String(e?.message ?? e)}`);
      setMsg('idle', '');
    }
  };

  const doImport = async (pkg: any) => {
    setMsg('importing', 'Import des données utilisateur…');
    try {
      // 1. Reconstruire le user avec son Map
      const userWithMap = {
        ...pkg.user,
        globalData: objToMap(pkg.user.globalData),
      };

      // Sérialisation pour AsyncStorage (Map → obj)
      const userForStorage = {
        ...pkg.user,
        globalData: mapToObj(objToMap(pkg.user.globalData)),
      };

      // 2. Sauvegarder currentUser
      await AsyncStorage.setItem('currentUser', JSON.stringify(userForStorage));

      // 3. Mettre à jour la liste des users
      const usersRaw = await AsyncStorage.getItem('users');
      const users: any[] = usersRaw ? JSON.parse(usersRaw) : [];
      const idx = users.findIndex((u: any) => u.username === pkg.username);
      if (idx >= 0) {
        users[idx] = userForStorage;
      } else {
        users.push(userForStorage);
      }
      await AsyncStorage.setItem('users', JSON.stringify(users));

      // 4. Bilans multi-rôles
      setMsg('importing', 'Import de l\'historique des bilans…');
      if (pkg.bilanAllRoles && typeof pkg.bilanAllRoles === 'object') {
        const bilanEntries: [string, string][] = Object.entries(pkg.bilanAllRoles).map(
          ([k, v]) => [k, JSON.stringify(v)]
        );
        if (bilanEntries.length > 0) await AsyncStorage.multiSet(bilanEntries);
      } else if (pkg.bilanMain && Array.isArray(pkg.bilanMain)) {
        // Compat version 1
        await AsyncStorage.setItem(
          `bilan_${pkg.username}_default`,
          JSON.stringify(pkg.bilanMain)
        );
      }

      // 5. Valeurs slider symptômes
      if (pkg.symptomValues && typeof pkg.symptomValues === 'object') {
        setMsg('importing', 'Import des valeurs symptômes…');
        const symptomEntries: [string, string][] = Object.entries(pkg.symptomValues).map(
          ([k, v]) => [k, JSON.stringify(v)]
        );
        if (symptomEntries.length > 0) await AsyncStorage.multiSet(symptomEntries);
      }

      // 6. Mettre à jour le contexte React
      setMsg('importing', 'Mise à jour du contexte…');
      await updateCurrentUserAsync(userWithMap);

      setSuccessMsg(`Données de "${pkg.username}" importées avec succès !\n\nL'application utilise maintenant les données transférées.`);
      setMsg('success', '');
    } catch (e: any) {
      Alert.alert('Erreur import', String(e?.message ?? e));
      setMsg('idle', '');
    }
  };

  const isLoading = status === 'exporting' || status === 'importing';

  return (
    <Modal
      visible={visible}
      transparent
      animationType="slide"
      onRequestClose={onClose}
    >
      <View style={styles.overlay}>
        <View style={styles.card}>
          <View style={styles.header}>
            <Text style={styles.title}>Transfert de données</Text>
            <TouchableOpacity onPress={onClose} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
              <AntDesign name="close" size={20} color="#888" />
            </TouchableOpacity>
          </View>

          {/* ── Chargement ── */}
          {isLoading && (
            <View style={styles.loadingContainer}>
              <ActivityIndicator size="large" color="#E8437B" />
              <Text style={styles.loadingText}>{statusMsg}</Text>
            </View>
          )}

          {/* ── Succès ── */}
          {status === 'success' && (
            <View style={styles.successContainer}>
              <AntDesign name="checkcircle" size={48} color="#00C100" />
              <Text style={styles.successText}>{successMsg}</Text>
              <Button text="Fermer" isSelected onPress={onClose} />
            </View>
          )}

          {/* ── Idle : boutons export / import ── */}
          {status === 'idle' && (
            <ScrollView showsVerticalScrollIndicator={false}>
              <Text style={styles.intro}>
                Transférez toutes vos données vers un autre téléphone via AirDrop, email ou messagerie — sans connexion internet.
              </Text>

              {/* Export */}
              <View style={styles.section}>
                <View style={styles.sectionHeader}>
                  <AntDesign name="upload" size={22} color="#E8437B" />
                  <Text style={styles.sectionTitle}>Exporter (ce téléphone)</Text>
                </View>
                <Text style={styles.sectionDesc}>
                  Génère un fichier contenant vos données et l'envoie à l'autre téléphone via le partage natif.
                </Text>
                {!currentUser && (
                  <Text style={styles.warningText}>⚠ Aucun utilisateur connecté.</Text>
                )}
                <Button
                  text="📤  Exporter mes données"
                  isSelected
                  onPress={handleExport}
                />
              </View>

              <View style={styles.divider} />

              {/* Import */}
              <View style={styles.section}>
                <View style={styles.sectionHeader}>
                  <AntDesign name="download" size={22} color="#555" />
                  <Text style={styles.sectionTitle}>Importer (ce téléphone)</Text>
                </View>
                <Text style={styles.sectionDesc}>
                  Sélectionnez le fichier .msdb reçu de l'autre téléphone pour importer les données.
                </Text>
                <Button
                  text="📥  Importer un fichier .msdb"
                  onPress={handleImport}
                />
              </View>

              <View style={styles.divider} />

              {/* Instructions */}
              <View style={styles.howto}>
                <Text style={styles.howtoTitle}>Comment faire ?</Text>
                <Text style={styles.howtoStep}>1. Sur le téléphone source → "Exporter"</Text>
                <Text style={styles.howtoStep}>2. Choisir AirDrop, WhatsApp, email… pour envoyer à l'autre tél</Text>
                <Text style={styles.howtoStep}>3. Sur le téléphone destinataire → "Importer" → sélectionner le fichier reçu</Text>
              </View>
            </ScrollView>
          )}
        </View>
      </View>
    </Modal>
  );
};

const styles = StyleSheet.create({
  overlay: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.55)',
    justifyContent: 'flex-end',
  },
  card: {
    backgroundColor: 'white',
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    padding: 24,
    maxHeight: '85%',
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 16,
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
  },
  intro: {
    fontSize: 13,
    color: '#666',
    marginBottom: 20,
    lineHeight: 19,
  },
  section: {
    marginVertical: 6,
  },
  sectionHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
    marginBottom: 6,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: '700',
  },
  sectionDesc: {
    fontSize: 12,
    color: '#888',
    marginBottom: 12,
    lineHeight: 18,
  },
  warningText: {
    fontSize: 12,
    color: '#c00',
    marginBottom: 8,
  },
  divider: {
    height: 1,
    backgroundColor: '#eee',
    marginVertical: 16,
  },
  howto: {
    backgroundColor: '#f8f8f8',
    borderRadius: 10,
    padding: 14,
    marginBottom: 8,
  },
  howtoTitle: {
    fontSize: 13,
    fontWeight: '700',
    marginBottom: 8,
    color: '#444',
  },
  howtoStep: {
    fontSize: 12,
    color: '#666',
    marginBottom: 5,
    lineHeight: 18,
  },
  loadingContainer: {
    alignItems: 'center',
    paddingVertical: 40,
    gap: 16,
  },
  loadingText: {
    fontSize: 14,
    color: '#666',
  },
  successContainer: {
    alignItems: 'center',
    paddingVertical: 24,
    gap: 16,
  },
  successText: {
    fontSize: 14,
    color: '#444',
    textAlign: 'center',
    lineHeight: 20,
  },
});

export default DataTransferPopup;