File size: 19,141 Bytes
f1602bc
315da52
32aac78
236e39c
f1602bc
 
 
c428e52
32aac78
f1602bc
ebd65f3
131c11c
f1602bc
32aac78
315da52
32aac78
c428e52
32aac78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63226fc
 
 
32aac78
 
 
236e39c
 
32aac78
 
236e39c
 
63226fc
5eb71d1
 
 
 
 
 
 
 
 
 
 
 
32aac78
236e39c
ebd65f3
236e39c
 
b240e2e
 
32aac78
131c11c
32aac78
131c11c
236e39c
5eb71d1
32aac78
5eb71d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236e39c
32aac78
 
ebd65f3
63226fc
32aac78
5eb71d1
b15f84b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5eb71d1
63226fc
5eb71d1
 
 
 
 
63226fc
5eb71d1
 
 
 
32aac78
131c11c
63226fc
131c11c
63226fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32aac78
 
 
5eb71d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63226fc
 
5eb71d1
 
 
63226fc
5eb71d1
 
 
 
131c11c
 
5eb71d1
131c11c
32aac78
131c11c
5eb71d1
131c11c
b15f84b
32aac78
5eb71d1
 
 
 
 
 
 
 
 
 
 
32aac78
 
5eb71d1
 
32aac78
63226fc
5eb71d1
63226fc
32aac78
5eb71d1
32aac78
5eb71d1
 
 
 
 
 
 
 
 
 
32aac78
 
63226fc
5eb71d1
63226fc
5eb71d1
63226fc
5eb71d1
236e39c
5eb71d1
 
 
236e39c
63226fc
5eb71d1
 
63226fc
5eb71d1
 
 
 
 
 
63226fc
 
 
 
 
 
 
 
 
 
 
 
 
5eb71d1
 
 
63226fc
 
 
 
5eb71d1
 
 
 
 
 
 
 
131c11c
5eb71d1
315da52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
// js/main.js

// --- INICIO: Importaciones ---
import { renderIaConfigForm, transcriptionProviders, getIaConfig } from './iaConfigModule.js';
import { initRecorder } from './recordingModule.js';
import { analyzeMedical } from './analysisModule.js';
import { copyText } from './clipboardModule.js';
import { analyzeLabResults, displayLabResults } from './labAnalysisModule.js';
// --- FIN: Importaciones ---

console.log("[Main] Script main.js cargado. Esperando DOMContentLoaded...");

window.addEventListener('DOMContentLoaded', () => {
  console.log("[Main] Evento DOMContentLoaded detectado.");

  // --- Variables y Estado ---
  let lastLabResultText = '';

  // --- Selecci贸n de Elementos DOM (con validaci贸n b谩sica) ---
  console.log("[Main] Seleccionando elementos...");
  const btnConfig = document.getElementById('btnConfig');             if (!btnConfig) console.error("!!! #btnConfig NO ENCONTRADO!");
  const modal = document.getElementById('configModal');                 if (!modal) console.error("!!! #configModal NO ENCONTRADO!");
  const transcriptEl = document.getElementById('transcript');             if (!transcriptEl) console.error("!!! #transcript NO ENCONTRADO!");
  const outputEnfermedadEl = document.getElementById('output-enfermedad'); if (!outputEnfermedadEl) console.error("!!! #output-enfermedad NO ENCONTRADO!");
  const outputExploracionEl = document.getElementById('output-exploracion'); if (!outputExploracionEl) console.error("!!! #output-exploracion NO ENCONTRADO!");
  const btnStart = document.getElementById('btnStart');                 if (!btnStart) console.error("!!! #btnStart NO ENCONTRADO!");
  const btnStop = document.getElementById('btnStop');                   if (!btnStop) console.error("!!! #btnStop NO ENCONTRADO!");
  const allTabButtons = document.querySelectorAll('.tab-button');         if (allTabButtons.length === 0) console.error("!!! No .tab-button encontrados!");
  const allTabContents = document.querySelectorAll('.tab-content');       if (allTabContents.length === 0) console.error("!!! No .tab-content encontrados!");
  const labInputText = document.getElementById('lab-input-text');         if (!labInputText) console.error("!!! #lab-input-text NO ENCONTRADO!");
  const btnAnalyzeLabs = document.getElementById('btnAnalyzeLabs');       if (!btnAnalyzeLabs) console.error("!!! #btnAnalyzeLabs NO ENCONTRADO!");
  const labLoadingIndicator = document.getElementById('lab-loading-indicator'); if (!labLoadingIndicator) console.error("!!! #lab-loading-indicator NO ENCONTRADO!");
  const filterAlteredLabsCheckbox = document.getElementById('filterAlteredLabs'); if (!filterAlteredLabsCheckbox) console.error("!!! #filterAlteredLabs NO ENCONTRADO!");
  const labResultsOutput = document.getElementById('lab-results-output');   if (!labResultsOutput) console.error("!!! #lab-results-output NO ENCONTRADO!");
  const btnCopyTranscript = document.getElementById('btnCopyTranscript');   if (!btnCopyTranscript) console.error("!!! #btnCopyTranscript NO ENCONTRADO!");
  const btnCopyAnalysis = document.getElementById('btnCopyAnalysis');     if (!btnCopyAnalysis) console.error("!!! #btnCopyAnalysis NO ENCONTRADO!");
  const btnCopyLabResults = document.getElementById('btnCopyLabResults');   if (!btnCopyLabResults) console.error("!!! #btnCopyLabResults NO ENCONTRADO!");
  console.log("[Main] Selecci贸n elementos finalizada.");

  // --- Funci贸n updateModelLabels (DENTRO de DOMContentLoaded) ---
  function updateModelLabels() {
    console.log("[Main] Ejecutando updateModelLabels...");
    // (C贸digo interno de la funci贸n sin cambios)
    try{ const cfg=getIaConfig(); const tP=cfg?.transcription?.provider; const tM=cfg?.transcription?.models?.[tP]||'N/A'; const lP=cfg?.llm?.provider; const lM=cfg?.llm?.model||'N/A'; const tL=document.getElementById('trans-model-label'); if(tL)tL.textContent=tM?`(${tM})`:''; const aL=document.getElementById('analysis-model-label'); if(aL)aL.textContent=lM?`(${lM})`:''; const labL=document.getElementById('lab-model-label'); if(labL)labL.textContent=lM?`(${lM})`:''; } catch(e){console.error("Error en updateModelLabels:",e)}
  }

  // --- Funci贸n para Limpiar Campos de UI ---
  function clearUIFields() {
    console.log('[Main] Ejecutando clearUIFields...');
    if (transcriptEl) transcriptEl.value = 'Aqu铆 aparecer谩 la transcripci贸n...'; // Valor inicial o ''
    if (outputEnfermedadEl) outputEnfermedadEl.textContent = '';
    if (outputExploracionEl) outputExploracionEl.textContent = '';
    // Tambi茅n limpiamos los campos de la pesta帽a de Laboratorio por consistencia
    if (labInputText) labInputText.value = '';
    if (labResultsOutput) labResultsOutput.innerHTML = '';
    lastLabResultText = ''; // Reiniciar variable de estado
    console.log('[Main] Campos de UI limpiados.');
  }

  // --- Configuraci贸n Inicial y Listeners ---
  try {
    updateModelLabels(); // Llamada inicial
    document.addEventListener('iaConfigChanged', updateModelLabels);
    renderIaConfigForm('iaConfigContainer');
    if(btnConfig) { btnConfig.addEventListener('click', () => { renderIaConfigForm('iaConfigContainer'); if (modal) modal.classList.add('active'); }); }
    if(modal) { modal.addEventListener('mousedown', e => { if (e.target === modal) modal.classList.remove('active'); }); }
  } catch(e) { console.error("Error en setup inicial (config/labels):", e); }

  // --- Listener AN脕LISIS M脡DICO ---
  try {
    document.addEventListener('transcriptionReady', async (e) => {
        console.log("[Main] Evento 'transcriptionReady' recibido.");
        const transcriptText = e.detail; if (!transcriptText) return;
        // Mostrar 'Analizando...' solo si los elementos existen
        if(outputEnfermedadEl) outputEnfermedadEl.textContent='Analizando...';
        if(outputExploracionEl) outputExploracionEl.textContent=''; // Limpiar el segundo campo
        try {
          const result = await analyzeMedical(transcriptText);
          console.log("[Main] An谩lisis m茅dico completado.");
          const sections = result.split(/\n\s*\n/);
          // Actualizar elementos solo si existen
          if(outputEnfermedadEl) outputEnfermedadEl.textContent = sections[0]?.trim() || '(No generado)';
          if(outputExploracionEl) outputExploracionEl.textContent = sections.slice(1).join('\n\n').trim() || '(No generado)';
        }
        catch (err) {
          console.error("Error en analyzeMedical:", err);
          if(outputEnfermedadEl) outputEnfermedadEl.textContent = `Error an谩lisis: ${err.message}`;
          if(outputExploracionEl) outputExploracionEl.textContent = ''; // Limpiar si hubo error
          alert(`Error an谩lisis m茅dico: ${err.message}`);
        }
    });
    console.log("[Main] Listener 'transcriptionReady' a帽adido.");
  } catch(e) { console.error("Error a帽adiendo listener 'transcriptionReady':", e); }

  // --- Inicializar Grabadora ---
  try {
    // La funci贸n getTranscriptionProviderUrl est谩 definida dentro de este try-catch
    function getTranscriptionProviderUrl() {
        console.log("[Main] Ejecutando getTranscriptionProviderUrl...");
        const cfg = getIaConfig();
        const providerValue = cfg?.transcription?.provider;

        if (providerValue) {
            const prov = transcriptionProviders.find(p => p.value === providerValue);
            if (prov?.url) {
                console.log(`[Main] URL encontrada para ${providerValue}: ${prov.url}`);
                return prov.url;
            } else {
                 console.warn(`[Main] URL no encontrada para el proveedor '${providerValue}'.`);
            }
        } else {
             console.warn('[Main] No se encontr贸 providerValue en cfg.transcription.provider.');
        }
        console.error('[Main] Fallo al obtener URL del proveedor. Retornando vac铆o.');
        return '';
     }
    if (btnStart && btnStop && transcriptEl && typeof initRecorder === 'function') {
      // Pasamos la funci贸n clearUIFields como callback
      initRecorder({
        btnStart,
        btnStop,
        transcriptEl,
        getProvider: getTranscriptionProviderUrl,
        clearFieldsCallback: clearUIFields
      });
    } else {
      console.error("Faltan elementos/funci贸n para initRecorder");
    }
  } catch(e) { console.error("Error inicializando Recorder:", e); }

  // --- Botones Copiar (An谩lisis M茅dico) --- (MODIFICADO CON FEEDBACK)
  try {
    // Bot贸n Copiar Transcripci贸n
    if (btnCopyTranscript && transcriptEl) {
        btnCopyTranscript.addEventListener('click', async () => {
            const textToCopy = transcriptEl.value;
            if (textToCopy && textToCopy !== 'Aqu铆 aparecer谩 la transcripci贸n...') {
                try {
                    await copyText(textToCopy);
                    // --- INICIO: L贸gica de Feedback Visual ---
                    const buttonElement = btnCopyTranscript;
                    const originalHtml = buttonElement.innerHTML;
                    buttonElement.innerHTML = '<i class="fas fa-check mr-2"></i>Copiado!';
                    buttonElement.disabled = true;
                    setTimeout(() => {
                        // Solo restaurar si el bot贸n sigue existiendo y est谩 deshabilitado
                        if (document.body.contains(buttonElement) && buttonElement.disabled) {
                            buttonElement.innerHTML = originalHtml;
                            buttonElement.disabled = false;
                        }
                    }, 2000);
                    // --- FIN: L贸gica de Feedback Visual ---
                } catch (err) {
                    console.error('Error copia transcripci贸n:', err);
                    alert('Error al copiar transcripci贸n.');
                    // Asegurarse de rehabilitar el bot贸n si falla la copia
                    if (document.body.contains(btnCopyTranscript)) {
                        btnCopyTranscript.disabled = false;
                    }
                }
            } else {
                alert('No hay transcripci贸n v谩lida para copiar.');
            }
        });
    } else {
        console.error("Faltan elementos para bot贸n Copiar Transcripci贸n.");
    }

    // Bot贸n Copiar An谩lisis M茅dico (Enfermedad + Exploraci贸n)
    if (btnCopyAnalysis && outputEnfermedadEl && outputExploracionEl) {
        btnCopyAnalysis.addEventListener('click', async () => {
            const textToCopy = `${outputEnfermedadEl.textContent || ''}\n\n${outputExploracionEl.textContent || ''}`.trim();
            // Validar que no est茅 vac铆o y no contenga mensajes de error o "no generado"
            if (textToCopy && !textToCopy.toLowerCase().includes('error') && !textToCopy.toLowerCase().includes('(no generado)')) {
                try {
                    await copyText(textToCopy);
                    // --- INICIO: L贸gica de Feedback Visual ---
                    const buttonElement = btnCopyAnalysis;
                    const originalHtml = buttonElement.innerHTML;
                    buttonElement.innerHTML = '<i class="fas fa-check mr-2"></i>Copiado!';
                    buttonElement.disabled = true;
                    setTimeout(() => {
                        // Solo restaurar si el bot贸n sigue existiendo y est谩 deshabilitado
                         if (document.body.contains(buttonElement) && buttonElement.disabled) {
                            buttonElement.innerHTML = originalHtml;
                            buttonElement.disabled = false;
                         }
                    }, 2000);
                    // --- FIN: L贸gica de Feedback Visual ---
                } catch (err) {
                    console.error('Error copia an谩lisis:', err);
                    alert('Error al copiar an谩lisis.');
                     // Asegurarse de rehabilitar el bot贸n si falla la copia
                     if (document.body.contains(btnCopyAnalysis)) {
                         btnCopyAnalysis.disabled = false;
                     }
                }
            } else {
                alert('No hay an谩lisis v谩lido para copiar.');
            }
        });
    } else {
         console.error("Faltan elementos para bot贸n Copiar An谩lisis.");
    }
  } catch(e) {
    console.error("Error a帽adiendo listeners botones Copiar (M茅dico):", e);
  }

  // --- Cambio de Pesta帽as ---
  try {
    function switchTab(clickedTab) {
      const targetContentId = clickedTab.dataset.contentId;
      const targetContentElement = document.getElementById(targetContentId);

      if(targetContentElement && !targetContentElement.classList.contains('active')){
        // Desactivar todos los botones y contenidos
        allTabButtons.forEach(button => {
          const activeClasses = button.dataset.activeClasses.split(' ').filter(c => c);
          const inactiveClasses = button.dataset.inactiveClasses.split(' ').filter(c => c);
          button.classList.remove(...activeClasses);
          button.classList.add(...inactiveClasses);
        });
        allTabContents.forEach(content => {
          content.classList.remove('active');
        });

        // Activar el bot贸n y contenido clickeado
        const activeClassesToAdd = clickedTab.dataset.activeClasses.split(' ').filter(c => c);
        const inactiveClassesToRemove = clickedTab.dataset.inactiveClasses.split(' ').filter(c => c);
        clickedTab.classList.remove(...inactiveClassesToRemove);
        clickedTab.classList.add(...activeClassesToAdd);
        targetContentElement.classList.add('active');
        console.log(`Pesta帽a activada: ${targetContentId}`);
      }
    }
    if(allTabButtons.length > 0){
      allTabButtons.forEach(button => {
        button.addEventListener('click', (e) => {
          switchTab(e.currentTarget);
        });
      });
      // Activar la primera pesta帽a por defecto si ninguna est谩 activa
      const initiallyActive = document.querySelector('.tab-button.bg-indigo-600'); // Busca la clase activa inicial del HTML
      if (initiallyActive && !document.querySelector('.tab-content.active')) {
          switchTab(initiallyActive);
      } else if (!document.querySelector('.tab-content.active') && allTabButtons.length > 0) {
          switchTab(allTabButtons[0]); // Activa la primera si no hay ninguna activa por defecto
      }
    } else {
      console.error("No se pueden a帽adir listeners a los botones de pesta帽a.");
    }
  } catch(e) { console.error("Error en setup Cambio de Pesta帽as:", e); }

  // --- ELIMINADO: Bloque del listener 'newRecordingStarted' ---

  // --- L贸gica Pesta帽a Laboratorio ---
  try {
    // Listener Analizar Laboratorio
    if (btnAnalyzeLabs && labInputText && labLoadingIndicator && filterAlteredLabsCheckbox && labResultsOutput) {
        btnAnalyzeLabs.addEventListener('click', async () => {
            console.log("[Main] Click en btnAnalyzeLabs.");
            const inputText = labInputText.value;
            if (!inputText.trim()) {
                alert("Por favor, pega los resultados del laboratorio en el 谩rea de texto.");
                return;
            }
            labLoadingIndicator.style.display = 'flex';
            btnAnalyzeLabs.disabled = true;
            filterAlteredLabsCheckbox.disabled = true;
            labResultsOutput.innerHTML = ''; // Limpiar resultados anteriores
            lastLabResultText = '';

            try {
                const resultText = await analyzeLabResults(inputText);
                console.log("RAW AI RESPONSE:", resultText);
                lastLabResultText = resultText; // Guardar el resultado crudo
                const filterIsActive = filterAlteredLabsCheckbox.checked;
                displayLabResults(resultText, labResultsOutput, filterIsActive); // Mostrar resultados

                // Llamada a updateModelLabels
                console.log("[Main] Intentando llamar a updateModelLabels desde listener btnAnalyzeLabs...");
                updateModelLabels();
                console.log("[Main] Llamada a updateModelLabels desde listener btnAnalyzeLabs completada.");

            } catch (error) {
                console.error("Error DENTRO listener btnAnalyzeLabs:", error);
                if(labResultsOutput) labResultsOutput.innerHTML = `<p class="text-red-600 font-semibold">Error al procesar: ${error.message}</p>`;
                alert(`Error al analizar resultados: ${error.message}`);
            } finally {
                labLoadingIndicator.style.display = 'none';
                btnAnalyzeLabs.disabled = false;
                filterAlteredLabsCheckbox.disabled = false;
            }
        });

        // Listener Checkbox Filtro
        filterAlteredLabsCheckbox.addEventListener('change', () => {
            if (!lastLabResultText || !labResultsOutput) return;
            const filterIsActive = filterAlteredLabsCheckbox.checked;
            displayLabResults(lastLabResultText, labResultsOutput, filterIsActive);
        });

    } else {
        console.error("Faltan elementos esenciales para la Pesta帽a de An谩lisis de Ex谩menes.");
    }

    // Listener Copiar Laboratorio (con feedback)
    if (btnCopyLabResults && labResultsOutput) {
        btnCopyLabResults.addEventListener('click', async () => {
            const currentOutputText = labResultsOutput.textContent?.trim();
            if(!currentOutputText || currentOutputText.startsWith('Error')) {
                alert('No hay resultados v谩lidos para copiar.');
                return;
            }
            try {
                await copyText(currentOutputText);
                // --- INICIO: L贸gica de Feedback Visual ---
                const buttonElement = btnCopyLabResults;
                const originalHtml = buttonElement.innerHTML;
                buttonElement.innerHTML = '<i class="fas fa-check mr-2"></i>Copiado!';
                buttonElement.disabled = true;
                setTimeout(() => {
                    // Solo restaurar si el bot贸n sigue existiendo y est谩 deshabilitado
                    if (document.body.contains(buttonElement) && buttonElement.disabled) {
                       buttonElement.innerHTML = originalHtml;
                       buttonElement.disabled = false;
                    }
                }, 2000);
                 // --- FIN: L贸gica de Feedback Visual ---
            } catch(e){
                console.error("Error al copiar resultados de laboratorio:", e);
                alert("Error al intentar copiar los resultados.");
                 // Asegurarse de rehabilitar el bot贸n si falla la copia
                 if (document.body.contains(btnCopyLabResults)) {
                     btnCopyLabResults.disabled = false;
                 }
            }
        });
    } else {
        console.error("Faltan elementos para el bot贸n Copiar Resultados de Laboratorio.");
    }
   } catch(e) {
       console.error("Error general en el setup de la Pesta帽a de An谩lisis de Ex谩menes:", e);
   }

  console.log("[Main] Configuraci贸n de listeners y UI inicial finalizada.");
}); // Fin de window.addEventListener('DOMContentLoaded', ...)