import 'package:drift/drift.dart';

/// 通用数据库 CRUD 接口。
///
/// 所有方法通过 Drift 的 [TableInfo]、[Insertable]、[Expression] 泛型操作，
/// 与具体表定义解耦，App 层按需传入对应 Table 即可。
///
/// 示例：
/// ```dart
/// await repo.insertOrReplace(db.users, companion);
/// final list = await repo.selectWhere(db.messages, (t) => t.chatId.equals(id));
/// ```
abstract class DatabaseRepository {
  // ── 插入 ─────────────────────────────────────────────────────────────────

  /// 插入或替换（主键冲突时删除原行再插入）。
  ///
  /// 注意：底层是 DELETE + INSERT，rowid 变更，触发 DELETE 级联。
  /// 如需原地更新，请使用 [insertOnConflictUpdate]。
  Future<void> insertOrReplace<T extends Table, D>(
    TableInfo<T, D> table,
    Insertable<D> companion,
  );

  /// 插入或忽略（主键冲突时跳过）。
  Future<void> insert<T extends Table, D>(
    TableInfo<T, D> table,
    Insertable<D> companion,
  );

  /// 批量插入或替换（主键冲突时删除原行再插入）。
  ///
  /// 注意：底层是 DELETE + INSERT，rowid 变更，触发 DELETE 级联。
  /// 如需原地更新，请使用 [batchInsertOnConflictUpdate]。
  Future<void> batchInsertOrReplace<T extends Table, D>(
    TableInfo<T, D> table,
    List<Insertable<D>> companions,
  );

  /// 插入，主键冲突时原地更新全部字段（INSERT ... ON CONFLICT DO UPDATE SET）。
  ///
  /// 与 [insertOrReplace] 的区别：
  /// - [insertOrReplace]        → DELETE + INSERT，rowid 变更，触发 DELETE 级联
  /// - [insertOnConflictUpdate] → 原地 UPDATE，rowid 不变，不触发 DELETE 级联
  ///
  /// 适用场景：upsert 语义，且不希望影响依赖 rowid 的其他逻辑。
  Future<void> insertOnConflictUpdate<T extends Table, D>(
    TableInfo<T, D> table,
    Insertable<D> companion,
  );

  /// 批量插入，主键冲突时原地更新全部字段。
  ///
  /// 与 [batchInsertOrReplace] 的区别同 [insertOnConflictUpdate]。
  Future<void> batchInsertOnConflictUpdate<T extends Table, D>(
    TableInfo<T, D> table,
    List<Insertable<D>> companions,
  );

  // ── 更新 ─────────────────────────────────────────────────────────────────

  /// 按条件更新。
  Future<void> updateWhere<T extends Table, D>(
    TableInfo<T, D> table,
    Insertable<D> companion,
    Expression<bool> Function(T) filter,
  );

  // ── 删除 ─────────────────────────────────────────────────────────────────

  /// 按条件删除。
  Future<void> deleteWhere<T extends Table, D>(
    TableInfo<T, D> table,
    Expression<bool> Function(T) filter,
  );

  /// 清空整张表。
  Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table);

  // ── 查询 ─────────────────────────────────────────────────────────────────

  /// 查询全部记录。
  Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table);

  /// 按条件查询。
  Future<List<D>> selectWhere<T extends Table, D>(
    TableInfo<T, D> table,
    Expression<bool> Function(T) filter,
  );

  /// 查询第一条匹配记录。
  Future<D?> selectFirst<T extends Table, D>(
    TableInfo<T, D> table,
    Expression<bool> Function(T) filter,
  );

  // ── 监听 ─────────────────────────────────────────────────────────────────

  /// 监听全部记录（实时流）。
  Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table);

  /// 按条件监听（实时流）。
  Stream<List<D>> watchWhere<T extends Table, D>(
    TableInfo<T, D> table,
    Expression<bool> Function(T) filter,
  );

  /// 监听第一条匹配记录（实时流）。
  Stream<D?> watchFirst<T extends Table, D>(
    TableInfo<T, D> table,
    Expression<bool> Function(T) filter,
  );

  // ── 原始 SQL ─────────────────────────────────────────────────────────────

  /// 执行原始查询，返回行数据。
  Future<List<QueryRow>> rawQuery(String sql, [List<Object?> args]);

  /// 执行原始语句（无返回值）。
  Future<void> rawExecute(String sql, [List<Object?> args]);

  // ── 统计 ─────────────────────────────────────────────────────────────────

  /// 统计记录数。
  Future<int> count<T extends Table, D>(
    TableInfo<T, D> table, {
    Expression<bool> Function(T)? filter,
  });
}
