import 'package:drift/drift.dart';
import 'package:im_app/data/local/drift/app_database.dart';
import 'package:im_app/domain/entities/favorite.dart';
import 'package:im_app/domain/repositories/favorite_repository.dart';
import 'package:storage_sdk/storage_sdk.dart';

class FavoriteRepositoryImpl implements FavoriteRepository {
  final StorageSdkApi _storage;

  FavoriteRepositoryImpl(this._storage);

  // ── DB row → Domain ──────────────────────────────────────────────────────

  Favorite _toEntity(DriftFavorite row) => Favorite(
    id: row.id,
    parentId: row.parentId,
    data: row.data,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
    deletedAt: row.deletedAt,
    source: row.source,
    userId: row.userId,
    authorId: row.authorId,
    typ: row.typ,
    tag: row.tag,
    isPin: row.isPin,
    chatTyp: row.chatTyp,
    isUploaded: row.isUploaded,
    urls: row.urls,
  );

  // ── Domain → DB companion (internal only) ────────────────────────────────

  FavoritesCompanion _toCompanion(Favorite favorite) => FavoritesCompanion(
    id: Value(favorite.id),
    parentId: Value(favorite.parentId),
    data: Value(favorite.data),
    createdAt: Value(favorite.createdAt),
    updatedAt: Value(favorite.updatedAt),
    deletedAt: Value(favorite.deletedAt),
    source: Value(favorite.source),
    userId: Value(favorite.userId),
    authorId: Value(favorite.authorId),
    typ: Value(favorite.typ),
    tag: Value(favorite.tag),
    isPin: Value(favorite.isPin),
    chatTyp: Value(favorite.chatTyp),
    isUploaded: Value(favorite.isUploaded),
    urls: Value(favorite.urls),
  );

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

  @override
  Stream<List<Favorite>> watchAll() {
    return _storage.watchAll<DriftFavorite>().map(
      (rows) => rows.map(_toEntity).toList(),
    );
  }

  @override
  Stream<Favorite?> watchById(int id) {
    return _storage
        .watchFirst<DriftFavorite, $FavoritesTable>((t) => t.id.equals(id))
        .map((row) => row != null ? _toEntity(row) : null);
  }

  @override
  Stream<List<Favorite>> watchByParentId(String parentId) {
    return _storage
        .watchWhere<DriftFavorite, $FavoritesTable>(
          (t) => t.parentId.equals(parentId),
        )
        .map((rows) => rows.map(_toEntity).toList());
  }

  // ── 读取 ─────────────────────────────────────────────────────────────────

  @override
  Future<List<Favorite>> getAll() async {
    final rows = await _storage.selectAll<DriftFavorite>();
    return rows.map(_toEntity).toList();
  }

  @override
  Future<Favorite?> getById(int id) async {
    final row = await _storage.selectFirst<DriftFavorite, $FavoritesTable>(
      (t) => t.id.equals(id),
    );
    return row != null ? _toEntity(row) : null;
  }

  @override
  Future<List<Favorite>> getByParentId(String parentId) async {
    final rows = await _storage.selectWhere<DriftFavorite, $FavoritesTable>(
      (t) => t.parentId.equals(parentId),
    );
    return rows.map(_toEntity).toList();
  }

  @override
  Future<List<Favorite>> getUnuploaded() async {
    final rows = await _storage.selectWhere<DriftFavorite, $FavoritesTable>(
      (t) => t.isUploaded.equals(0),
    );
    return rows.map(_toEntity).toList();
  }

  // ── 写入 ─────────────────────────────────────────────────────────────────

  @override
  Future<void> insertOrReplace(Favorite favorite) async {
    await _storage.insertOrReplace<DriftFavorite>(_toCompanion(favorite));
  }

  @override
  Future<void> insertOrReplaceAll(List<Favorite> favorites) async {
    await _storage.batchInsertOrReplace<DriftFavorite>(
      favorites.map(_toCompanion).toList(),
    );
  }

  @override
  Future<void> update(Favorite favorite) async {
    await _storage.updateWhere<DriftFavorite, $FavoritesTable>(
      _toCompanion(favorite),
      (t) => t.id.equals(favorite.id),
    );
  }

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

  @override
  Future<void> delete(int id) async {
    await _storage.deleteWhere<DriftFavorite, $FavoritesTable>(
      (t) => t.id.equals(id),
    );
  }

  @override
  Future<void> deleteByParentId(String parentId) async {
    await _storage.deleteWhere<DriftFavorite, $FavoritesTable>(
      (t) => t.parentId.equals(parentId),
    );
  }

  @override
  Future<void> clear() async {
    await _storage.deleteAll<DriftFavorite>();
  }
}
