// SPDX-FileCopyrightText: 2026 FocusFlow contributors
// SPDX-License-Identifier: AGPL-3.0-only

part of '../../encrypted_backup.dart';

/// Create an encrypted backup of the scheduler SQLite file.
///
/// Defaults:
/// - Source DB: `~/ADHD_Scheduler/scheduler.sqlite`
/// - Backup dir: `~/ADHD_Scheduler/backups`
/// - File name: `yyyymmdd_hhmm.db.enc`
Future<File> createEncryptedBackup({
  required String passphrase,
  File? sqliteFile,
  Directory? backupDirectory,
  DateTime? now,
}) async {
  final source = sqliteFile ?? defaultSchedulerSqliteFile();
  logger.info(() => 'Encrypted backup started. sourcePath=${source.path}');
  if (!await source.exists()) {
    logger.warn(() =>
        'Encrypted backup source file missing. sourcePath=${source.path}');
    throw BackupException('SQLite file does not exist: ${source.path}');
  }

  final destinationDirectory =
      backupDirectory ?? defaultSchedulerBackupDirectory();
  await destinationDirectory.create(recursive: true);

  final timestamp = _backupTimestamp(now ?? DateTime.now());
  final destination = await _nextAvailableBackupFile(
    destinationDirectory,
    '$timestamp$_fileExtension',
  );

  final plaintext = await source.readAsBytes();
  final encoded = await _encryptBytes(
    passphrase: passphrase,
    plaintext: plaintext,
  );
  final output = await destination.writeAsBytes(encoded, flush: true);
  logger.info(() => 'Encrypted backup completed. sourcePath=${source.path} '
      'destinationPath=${output.path} sourceBytes=${plaintext.length} '
      'encodedBytes=${encoded.length}');
  return output;
}

/// Restore an encrypted backup over the scheduler SQLite file.
///
/// Defaults to restoring into `~/ADHD_Scheduler/scheduler.sqlite`. Tests and
/// tools can pass [targetFile] to restore into a temp or alternate database.
Future<void> restoreEncryptedBackup(
  File backup,
  String passphrase, {
  File? targetFile,
}) async {
  logger.info(
      () => 'Encrypted backup restore started. backupPath=${backup.path}');
  if (!await backup.exists()) {
    logger.warn(() =>
        'Encrypted backup restore source missing. backupPath=${backup.path}');
    throw BackupException('Backup file does not exist: ${backup.path}');
  }

  final plaintext = await _decryptBytes(
    passphrase: passphrase,
    encoded: await backup.readAsBytes(),
  );
  final target = targetFile ?? defaultSchedulerSqliteFile();
  await target.parent.create(recursive: true);

  final temporary = File('${target.path}.restore.tmp');
  await temporary.writeAsBytes(plaintext, flush: true);
  if (await target.exists()) {
    await target.delete();
  }
  await temporary.rename(target.path);
  logger.info(
      () => 'Encrypted backup restore completed. backupPath=${backup.path} '
          'targetPath=${target.path} restoredBytes=${plaintext.length}');
}
