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

class TagRepositoryImpl implements TagRepository {
  final StorageSdkApi _storage;

  TagRepositoryImpl(this._storage);

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

  Tag _toEntity(DriftTag row) => Tag(
    id: row.id,
    uid: row.uid,
    name: row.name,
    type: row.type,
    createdAt: row.createdAt,
    updatedAt: row.updatedAt,
    addIndex: row.addIndex,
  );

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

  TagsCompanion _toCompanion(Tag tag) => TagsCompanion(
    id: tag.id != null ? Value(tag.id!) : const Value.absent(),
    uid: Value(tag.uid),
    name: Value(tag.name),
    type: Value(tag.type),
    createdAt: Value(tag.createdAt),
    updatedAt: Value(tag.updatedAt),
    addIndex: Value(tag.addIndex),
  );

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

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

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

  @override
  Stream<List<Tag>> watchByUid(int uid) {
    return _storage
        .watchWhere<DriftTag, $TagsTable>((t) => t.uid.equals(uid))
        .map((rows) => rows.map(_toEntity).toList());
  }

  @override
  Stream<List<Tag>> watchByType(int type) {
    return _storage
        .watchWhere<DriftTag, $TagsTable>((t) => t.type.equals(type))
        .map((rows) => rows.map(_toEntity).toList());
  }

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

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

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

  @override
  Future<List<Tag>> getByUid(int uid) async {
    final rows = await _storage.selectWhere<DriftTag, $TagsTable>(
      (t) => t.uid.equals(uid),
    );
    return rows.map(_toEntity).toList();
  }

  @override
  Future<List<Tag>> getByType(int type) async {
    final rows = await _storage.selectWhere<DriftTag, $TagsTable>(
      (t) => t.type.equals(type),
    );
    return rows.map(_toEntity).toList();
  }

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

  @override
  Future<void> insert(Tag tag) async {
    await _storage.insert<DriftTag>(_toCompanion(tag));
  }

  @override
  Future<void> insertOrReplace(Tag tag) async {
    await _storage.insertOrReplace<DriftTag>(_toCompanion(tag));
  }

  @override
  Future<void> insertOrReplaceAll(List<Tag> tags) async {
    await _storage.batchInsertOrReplace<DriftTag>(
      tags.map(_toCompanion).toList(),
    );
  }

  @override
  Future<void> update(Tag tag) async {
    if (tag.id == null) return;
    await _storage.updateWhere<DriftTag, $TagsTable>(
      _toCompanion(tag),
      (t) => t.id.equals(tag.id!),
    );
  }

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

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

  @override
  Future<void> deleteByUid(int uid) async {
    await _storage.deleteWhere<DriftTag, $TagsTable>((t) => t.uid.equals(uid));
  }

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