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

part of '../sqlite_repositories.dart';

/// Owns a SQLite database handle and its application unit-of-work adapter.
final class SqliteApplicationRuntime {
  /// Creates a runtime from an already-open [db].
  SqliteApplicationRuntime({
    required this.db,
    String defaultOwnerId = defaultV1OwnerId,
  }) : applicationStore = SqliteApplicationUnitOfWork(
          db,
          defaultOwnerId: defaultOwnerId,
        );

  /// Default fixed owner used by the V1 local runtime.
  static const defaultV1OwnerId = 'owner-1';

  /// Default fixed owner time zone used by the V1 local runtime.
  static const defaultV1TimeZoneId = 'UTC';

  /// Default project id used for V1 quick capture.
  static const defaultV1ProjectId = 'home';

  /// Open scheduler runtime state from the SQLite file at [path].
  static Future<SqliteApplicationRuntime> open({
    required String path,
    String defaultOwnerId = defaultV1OwnerId,
  }) async {
    core.logger.info(() => 'Opening SQLite application runtime. '
        'path=$path defaultOwnerId=$defaultOwnerId');
    final file = File(path);
    await file.parent.create(recursive: true);
    final runtime = SqliteApplicationRuntime(
      db: SchedulerDb(NativeDatabase(file)),
      defaultOwnerId: defaultOwnerId,
    );
    core.logger.info(() => 'SQLite application runtime opened. '
        'path=$path defaultOwnerId=$defaultOwnerId');
    return runtime;
  }

  /// Shared SQLite database handle.
  final SchedulerDb db;

  /// Application transaction boundary backed by [db].
  final SqliteApplicationUnitOfWork applicationStore;

  /// Inserts required owner settings and default project rows when absent.
  Future<core.ApplicationResult<void>> bootstrap({
    String ownerId = defaultV1OwnerId,
    String timeZoneId = defaultV1TimeZoneId,
    String defaultProjectId = defaultV1ProjectId,
  }) {
    core.logger.info(() => 'SQLite application bootstrap started. '
        'ownerId=$ownerId timeZoneId=$timeZoneId defaultProjectId=$defaultProjectId');
    return _guardApplicationErrors(() {
      return db.transaction(() async {
        final repositories = _SqliteApplicationRepositories(
          db,
          defaultOwnerId: ownerId,
        );
        final settings = await repositories.ownerSettings.findByOwnerId(
          ownerId,
        );
        if (settings == null) {
          core.logger.finer(() => 'SQLite bootstrap creating owner settings. '
              'ownerId=$ownerId timeZoneId=$timeZoneId');
          await repositories.ownerSettings.save(
            core.OwnerSettings(
              ownerId: ownerId,
              timeZoneId: timeZoneId,
              compactModeEnabled: true,
            ),
          );
        }

        final project = await repositories.projects.findById(defaultProjectId);
        if (project == null) {
          core.logger.finer(() => 'SQLite bootstrap creating default project. '
              'ownerId=$ownerId projectId=$defaultProjectId');
          await repositories.projects.save(
            core.ProjectProfile(
              id: defaultProjectId,
              name: 'Home',
              colorKey: 'project-home',
            ),
          );
        }

        core.logger.info(() => 'SQLite application bootstrap completed. '
            'ownerId=$ownerId createdSettings=${settings == null} '
            'createdProject=${project == null}');
        return core.ApplicationResult.success(null);
      });
    });
  }

  /// Closes the underlying SQLite database.
  Future<void> close() async {
    core.logger.info(() => 'Closing SQLite application runtime.');
    await db.close();
    core.logger.info(() => 'SQLite application runtime closed.');
  }
}
