import { Injectable } from '@angular/core'; import { Filesystem, Directory, Encoding } from '@capacitor/filesystem'; import { FilePicker } from '@capawesome/capacitor-file-picker'; import { EventoAcademico } from './data'; @Injectable({ providedIn: 'root' }) export class CsvStorageService { private readonly FILE_NAME = 'aulas_unicaba_datos.csv'; constructor() {} private async ensurePermissions(): Promise { try { let status = await Filesystem.checkPermissions(); if (status.publicStorage !== 'granted') { status = await Filesystem.requestPermissions(); } return status.publicStorage === 'granted'; } catch (e) { return true; } } async saveUserDataToCsv(favoritos: string[], eventos: EventoAcademico[]) { try { const hasPermission = await this.ensurePermissions(); if (!hasPermission) { console.warn('Permisos denegados para escribir en Documents'); return; } let csvContent = 'tipo,materia,id_o_valor,extra1,extra2,extra3,extra4\n'; // Filas de favoritos favoritos.forEach(codigo => { csvContent += `favorito,${codigo},,,,\n`; }); // Filas de eventos eventos.forEach(ev => { // Formato: evento,CODIGO,ID,TIPO,FECHA,AULA,LINK,NOTAS // Para simplificar el CSV sin escapar comas en notas, reemplazamos comas por punto y coma const notasEscaped = (ev.notas || '').replace(/,/g, ';'); csvContent += `evento,${ev.materiaCodigo},${ev.id},${ev.tipo},${ev.fecha},${ev.aula || ''},${ev.link || ''},${notasEscaped}\n`; }); // Intentamos borrar si existe try { await Filesystem.deleteFile({ path: this.FILE_NAME, directory: Directory.Documents }); } catch (e) {} await Filesystem.writeFile({ path: this.FILE_NAME, data: csvContent, directory: Directory.Documents, encoding: Encoding.UTF8 }); console.log('CSV con datos de usuario guardado en Documents'); } catch (e) { console.error('Error al guardar el CSV:', e); } } async loadUserDataFromCsv(): Promise<{ favoritos: string[], eventos: EventoAcademico[] } | null> { try { const hasPermission = await this.ensurePermissions(); if (!hasPermission) return null; const contents = await Filesystem.readFile({ path: this.FILE_NAME, directory: Directory.Documents, encoding: Encoding.UTF8 }); if (!contents.data) return null; const lines = contents.data.toString().split('\n'); const favs: string[] = []; const evs: EventoAcademico[] = []; for (let i = 1; i < lines.length; i++) { const line = lines[i].trim(); if (!line) continue; const parts = line.split(','); const tipo = parts[0]; if (tipo === 'favorito') { if (parts.length > 1 && parts[1]) { favs.push(parts[1]); } } else if (tipo === 'evento') { // evento,materia,id,tipo_ev,fecha,aula,link,notas if (parts.length >= 5) { evs.push({ materiaCodigo: parts[1], id: parts[2], tipo: parts[3] as any, fecha: parts[4], aula: parts[5] || '', link: parts[6] || '', notas: (parts[7] || '').replace(/;/g, ',') }); } } } return { favoritos: favs, eventos: evs }; } catch (e) { return null; } } async importFavoritesFromFilePicker(): Promise { try { const result = await FilePicker.pickFiles({ types: ['text/csv', 'text/comma-separated-values', '.csv'], readData: true }); const file = result.files[0]; if (!file || !file.data) return null; const text = decodeURIComponent(escape(window.atob(file.data))); const lines = text.split('\n'); const favs: string[] = []; for (let i = 1; i < lines.length; i++) { const line = lines[i].trim(); if (!line) continue; const parts = line.split(','); const tipo = parts[0]; if (tipo === 'favorito') { if (parts.length > 1 && parts[1]) { favs.push(parts[1]); } } // Nota: para el Picker manual solo recuperamos favoritos por ahora para simplicidad, // o podríamos reusar la lógica de loadUserDataFromCsv si el CSV es idéntico. } if (favs.length > 0) { await this.saveUserDataToCsv(favs, []); return favs; } return null; } catch(e) { console.warn('File picker cancelado o falló', e); return null; } } }