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

class SoundRepositoryImpl implements SoundRepository {
  final StorageSdkApi _storage;

  SoundRepositoryImpl(this._storage);

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

  Sound _toEntity(DriftSound row) => Sound(
    id: row.id,
    filePath: row.filePath,
    typ: row.typ,
    name: row.name,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
    deletedAt: row.deletedAt,
    channelGroupId: row.channelGroupId,
    isDefault: row.isDefault,
  );

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

  SoundsCompanion _toCompanion(Sound sound) => SoundsCompanion(
    id: Value(sound.id),
    filePath: Value(sound.filePath),
    typ: Value(sound.typ),
    name: Value(sound.name),
    createdAt: Value(sound.createdAt),
    updatedAt: Value(sound.updatedAt),
    deletedAt: Value(sound.deletedAt),
    channelGroupId: Value(sound.channelGroupId),
    isDefault: Value(sound.isDefault),
  );

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

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

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

  @override
  Stream<List<Sound>> watchByType(int typ) {
    return _storage
        .watchWhere<DriftSound, $SoundsTable>((t) => t.typ.equals(typ))
        .map((rows) => rows.map(_toEntity).toList());
  }

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

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

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

  @override
  Future<List<Sound>> getByType(int typ) async {
    final rows = await _storage.selectWhere<DriftSound, $SoundsTable>(
      (t) => t.typ.equals(typ),
    );
    return rows.map(_toEntity).toList();
  }

  @override
  Future<List<Sound>> getByChannelGroup(int channelGroupId) async {
    final rows = await _storage.selectWhere<DriftSound, $SoundsTable>(
      (t) => t.channelGroupId.equals(channelGroupId),
    );
    return rows.map(_toEntity).toList();
  }

  @override
  Future<List<Sound>> getDefaults() async {
    final rows = await _storage.selectWhere<DriftSound, $SoundsTable>(
      (t) => t.isDefault.equals(1),
    );
    return rows.map(_toEntity).toList();
  }

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

  @override
  Future<void> insertOrReplace(Sound sound) async {
    await _storage.insertOrReplace<DriftSound>(_toCompanion(sound));
  }

  @override
  Future<void> insertOrReplaceAll(List<Sound> sounds) async {
    await _storage.batchInsertOrReplace<DriftSound>(
      sounds.map(_toCompanion).toList(),
    );
  }

  @override
  Future<void> update(Sound sound) async {
    await _storage.updateWhere<DriftSound, $SoundsTable>(
      _toCompanion(sound),
      (t) => t.id.equals(sound.id),
    );
  }

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

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

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