// ═══════════════════════════════════════════════════════════════
// services/ConsultSync.ts
//
// Applique les "writes" créés par le médecin pendant la session
// de consultation dans le compte local du patient.
//
// Appelé depuis ConsultSharePopup après sync.php.
// ═══════════════════════════════════════════════════════════════
import AsyncStorage from '@react-native-async-storage/async-storage';
// FIX étape 4 : lexique pour reconstruire symptoms[] à partir de values{} d'un bilan médecin
import symptomesLex from '@/assets/json/symptomes.json';

// Map id → info symptôme (chargé une fois)
const SYM_LEX_MAP: Record<number, any> = (() => {
  const m: Record<number, any> = {};
  for (const s of (symptomesLex as any[])) {
    if (s && typeof s.id === 'number') m[s.id] = s;
  }
  return m;
})();

const mapToObj = (m: any): Record<string, any> => {
  if (!m || !(m instanceof Map)) return m ?? {};
  const o: Record<string, any> = {};
  for (const [k, v] of m.entries()) o[String(k)] = v;
  return o;
};

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]));
};

export interface ConsultWrite {
  id: number;
  action_type: 'bilan' | 'symptom_value' | 'note' | 'suivi_update';
  payload: Record<string, any>;
  cree_le: string;
}

// ── Appliquer tous les writes dans le User patient ──────────────
export async function applyConsultWrites(
  writes: ConsultWrite[],
  username: string
): Promise<void> {
  if (!writes || writes.length === 0) return;

  // Lire le User depuis AsyncStorage
  const currentUserRaw = await AsyncStorage.getItem('currentUser');
  if (!currentUserRaw) return;
  const user = JSON.parse(currentUserRaw);
  if (!user || user.username !== username) return;

  // Convertir globalData en Map pour manipulation
  const globalData: Map<number, any> = objToMap(user.globalData);
  let bilan: any[]    = user.bilan ?? [];
  let suivi: any[]    = user.suivi ?? [];
  let dossier: any    = user.dossier ?? { carnetdebord: [], antecedents: [], allergies: [], vaccins: [], remarks: [] };

  for (const write of writes) {
    const p = write.payload;
    const evaluateur = p._evaluateur_medecin ?? null;
    const dateWrite = write.cree_le ?? new Date().toISOString();

    switch (write.action_type) {

      // ── Bilan créé par le médecin → ajouté au bilan[] du patient
      case 'bilan': {
        // FIX étape 4 : reconstituer symptoms[] à partir de values{} + lexique
        // (les bilans médecin viennent avec values:{symId:val}, mais dossierbilan
        // itère bilan.symptoms[{name,value,valMax,...}])
        let enrichedSymptoms = Array.isArray(p.symptoms) ? p.symptoms : undefined;
        if (!enrichedSymptoms && p.values && typeof p.values === 'object') {
          enrichedSymptoms = Object.entries(p.values).map(([symId, val]) => {
            const ref = SYM_LEX_MAP[Number(symId)];
            return {
              id:      Number(symId),
              name:    ref?.name ?? String(symId),
              surname: ref?.surname ?? '',
              value:   val,
              valMin:  typeof ref?.valMin === 'number' ? ref.valMin : 0,
              valMax:  typeof ref?.valMax === 'number' && ref.valMax > 0 ? ref.valMax : 10,
              type:    ref?.type ?? 'Alpha',
              unit:    ref?.unit ?? '',
            };
          });
        }
        const bilanEntry = {
          ...p,
          id:         p.id ?? `consult_bilan_${write.id}_${Date.now()}`,
          date:       p.date ?? dateWrite,
          symptoms:   enrichedSymptoms ?? [],
          evaluateur: evaluateur
            ? `Dr ${evaluateur.prenom} ${evaluateur.nom} (RPPS: ${evaluateur.rpps})`
            : 'Médecin',
          _from_consult: true,
        };
        // Éviter les doublons
        if (!bilan.find((b: any) => b.id === bilanEntry.id)) {
          bilan = [...bilan, bilanEntry];
        }
        // Aussi sauvegarder dans AsyncStorage bilan_{username}_{role}
        const bilanKey = `bilan_${username}_${p._role ?? 'default'}`;
        const rawBilans = await AsyncStorage.getItem(bilanKey);
        const bilanList: any[] = rawBilans ? JSON.parse(rawBilans) : [];
        if (!bilanList.find((b: any) => b.id === bilanEntry.id)) {
          await AsyncStorage.setItem(bilanKey, JSON.stringify([...bilanList, bilanEntry]));
        }
        break;
      }

      // ── Valeur de symptôme → injectée dans globalData
      case 'symptom_value': {
        const symId = Number(p.symptom_id ?? p.symId);
        if (!symId || isNaN(symId)) break;
        const val    = p.value ?? p.valeur;
        const stack  = globalData.get(symId) ?? { id: symId, values: [], valMin: null, valMax: null, Frequence: 0, Evaluateur: '' };
        const point  = {
          date:       dateWrite,
          valeur:     val,
          patient:    username,
          role:       'medecin',
          evaluateur: evaluateur ? `Dr ${evaluateur.prenom} ${evaluateur.nom}` : 'Médecin',
        };
        const newValues = [...(stack.values ?? []), point].sort(
          (a: any, b: any) => new Date(a.date).getTime() - new Date(b.date).getTime()
        );
        const nums = newValues.map((v: any) => Number(v.valeur)).filter((n: number) => !isNaN(n));
        globalData.set(symId, {
          ...stack,
          values: newValues,
          valMin: nums.length ? Math.min(...nums) : null,
          valMax: nums.length ? Math.max(...nums) : null,
          Evaluateur: evaluateur ? `Dr ${evaluateur.prenom} ${evaluateur.nom}` : 'Médecin',
        });
        break;
      }

      // ── Note/commentaire → carnet de bord (indexé par label section)
      // FIX étape 4 : carnetdebordpage attend { [label]: entry[] }, pas un tableau plat.
      // Les notes du médecin vont dans un label dédié "Consultations médecin"
      // (sauf si p.section est fourni pour cibler un label spécifique).
      case 'note': {
        const note = {
          date:   dateWrite,
          text:   p.texte ?? p.note ?? '',   // 'text' pour cohérence avec entries patient
          texte:  p.texte ?? p.note ?? '',   // 'texte' conservé pour compat
          auteur: evaluateur ? `Dr ${evaluateur.prenom} ${evaluateur.nom}` : 'Médecin',
          _from_consult: true,
        };
        const sectionLabel = p.section || p.label || 'Consultations médecin';
        const existingCarnet = (dossier.carnetdebord && typeof dossier.carnetdebord === 'object' && !Array.isArray(dossier.carnetdebord))
          ? dossier.carnetdebord
          : {};
        const existingEntries = existingCarnet[sectionLabel] ?? [];
        dossier = {
          ...dossier,
          carnetdebord: {
            ...existingCarnet,
            [sectionLabel]: [...existingEntries, note],
          },
        };
        break;
      }

      // ── Mise à jour de suivi → ajouter une entry au suivi concerné
      case 'suivi_update': {
        const suiviId = p.suivi_id;
        if (!suiviId) break;
        const entry = {
          date:       dateWrite,
          values:     p.values ?? {},
          score:      p.score ?? null,
          scoreMax:   p.scoreMax ?? null,
          evaluateur: evaluateur ? `Dr ${evaluateur.prenom} ${evaluateur.nom}` : 'Médecin',
          _from_consult: true,
        };
        suivi = suivi.map((s: any) => {
          if (s.id !== suiviId) return s;
          const existingEntries: any[] = s.entries ?? [];
          // Éviter les doublons par date
          if (existingEntries.find((e: any) => e.date === entry.date)) return s;
          return { ...s, entries: [...existingEntries, entry] };
        });
        break;
      }
    }
  }

  // Sauvegarder le User mis à jour
  const updatedUser = {
    ...user,
    bilan,
    suivi,
    dossier,
    globalData: mapToObj(globalData),
  };

  // Lire + mettre à jour la liste users
  const usersRaw = await AsyncStorage.getItem('users');
  const users: any[] = usersRaw ? JSON.parse(usersRaw) : [];
  const updatedUsers = users.map((u: any) =>
    u.username === username ? updatedUser : u
  );

  await Promise.all([
    AsyncStorage.setItem('currentUser', JSON.stringify(updatedUser)),
    AsyncStorage.setItem('users', JSON.stringify(updatedUsers)),
    // Aussi sauvegarder les valeurs de symptômes dans @symptom:lastValue
    ...Array.from(globalData.entries()).map(([symId, stack]) =>
      AsyncStorage.setItem(
        `@symptom:lastValue:${username}:${symId}`,
        JSON.stringify(stack)
      )
    ),
  ]);
}
