1import 'dart:convert';
  2
  3import 'package:blood_pressure_app/features/export_import/import_preview_dialoge.dart';
  4import 'package:blood_pressure_app/l10n/app_localizations.dart';
  5import 'package:blood_pressure_app/model/export_import/csv_converter.dart';
  6import 'package:blood_pressure_app/model/export_import/csv_record_parsing_actor.dart';
  7import 'package:blood_pressure_app/model/storage/export_columns_store.dart';
  8import 'package:blood_pressure_app/model/storage/storage.dart';
  9import 'package:file_picker/file_picker.dart';
 10import 'package:flutter/material.dart';
 11import 'package:flutter_bloc/flutter_bloc.dart';
 12import 'package:health_data_store/health_data_store.dart';
 13import 'package:provider/provider.dart';
 14import 'package:sqflite/sqflite.dart';
 15
 16/// Text button to import entries like configured in the context.
 17class ImportButton extends StatelessWidget {
 18  /// Create text button to import entries like configured in the context.
 19  const ImportButton({super.key});
 20
 21  @override
 22  Widget build(BuildContext context) => TextButton.icon(
 23    label: Text(AppLocalizations.of(context)!.import),
 24    icon: Icon(Icons.file_upload_outlined),
 25    onPressed: () async {
 26      final localizations = AppLocalizations.of(context)!;
 27      final messenger = ScaffoldMessenger.of(context);
 28
 29      final file = (await FilePicker.platform.pickFiles(
 30        withData: true,
 31      ))?.files.firstOrNull;
 32      if (file == null) {
 33        messenger.showSnackBar(SnackBar(content: Text(localizations.errNoFileOpened)));
 34        return;
 35      }
 36      if (!context.mounted) return;
 37      switch(file.extension?.toLowerCase()) {
 38        case 'csv':
 39          final binaryContent = file.bytes;
 40          if (binaryContent == null) {
 41            messenger.showSnackBar(SnackBar(content: Text(localizations.errCantReadFile)));
 42            return;
 43          }
 44          if (!context.mounted) return;
 45          final csvSettings = Provider.of<CsvExportSettings>(context, listen: false);
 46          final exportColumnsManager = Provider.of<ExportColumnsManager>(context, listen: false);
 47          final converter = CsvConverter(
 48            csvSettings,
 49            exportColumnsManager,
 50            await RepositoryProvider.of<MedicineRepository>(context).getAll(),
 51          );
 52          if (!context.mounted) return;
 53          final importedRecords = await showImportPreview(
 54            context,
 55            CsvRecordParsingActor(
 56              converter,
 57              utf8.decode(binaryContent),
 58            ),
 59            exportColumnsManager,
 60            Provider.of<Settings>(context, listen: false).bottomAppBars,
 61          );
 62          if (importedRecords == null || !context.mounted) return;
 63          final bpRepo = RepositoryProvider.of<BloodPressureRepository>(context);
 64          final noteRepo = RepositoryProvider.of<NoteRepository>(context);
 65          final intakeRepo = RepositoryProvider.of<MedicineIntakeRepository>(context);
 66          await Future.forEach<FullEntry>(importedRecords, (e) async {
 67            if (e.sys != null || e.dia != null || e.pul != null) {
 68              await bpRepo.add(e.$1);
 69            }
 70            if (e.note != null || e.color != null) {
 71              await noteRepo.add(e.$2);
 72            }
 73            if (e.$3.isNotEmpty) {
 74              await Future.forEach(e.$3, intakeRepo.add);
 75            }
 76          });
 77          messenger.showSnackBar(SnackBar(content: Text(localizations.importSuccess(importedRecords.length))));
 78          break;
 79        case 'db':
 80          if (file.path == null) return;
 81          final bpRepo = RepositoryProvider.of<BloodPressureRepository>(context);
 82          final noteRepo = RepositoryProvider.of<NoteRepository>(context);
 83          final intakeRepo = RepositoryProvider.of<MedicineIntakeRepository>(context);
 84
 85          final List<BloodPressureRecord> records = [];
 86          final List<Note> notes = [];
 87          final List<MedicineIntake> intakes = [];
 88          try {
 89            final db = await openReadOnlyDatabase(file.path!);
 90            final importedDB = await HealthDataStore.load(db, true);
 91            records.addAll(await importedDB.bpRepo.get(DateRange.all()));
 92            notes.addAll(await importedDB.noteRepo.get(DateRange.all()));
 93            intakes.addAll(await importedDB.intakeRepo.get(DateRange.all()));
 94            await db.close();
 95          } catch (e) {
 96            // DB doesn't conform new format
 97          }
 98
 99
100          await Future.forEach(records, bpRepo.add);
101          await Future.forEach(notes, noteRepo.add);
102          await Future.forEach(intakes, intakeRepo.add);
103
104          messenger.showSnackBar(SnackBar(content: Text(localizations.importSuccess(records.length))));
105          break;
106        default:
107          messenger.showSnackBar(SnackBar(content: Text(localizations.errWrongImportFormat)));
108      }
109    },
110  );
111}