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

class GroupRepositoryImpl implements GroupRepository {
  final StorageSdkApi _storage;

  GroupRepositoryImpl(this._storage);

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

  Group _toEntity(DriftGroup row) => Group(
    id: row.id,
    userJoinDate: row.userJoinDate,
    name: row.name,
    profile: row.profile,
    icon: row.icon,
    iconGaussian: row.iconGaussian,
    permission: row.permission,
    admin: row.admin,
    members: row.members,
    owner: row.owner,
    admins: row.admins,
    visible: row.visible,
    speakInterval: row.speakInterval,
    groupType: row.groupType,
    roomType: row.roomType,
    maxNumber: row.maxNumber,
    channelId: row.channelId,
    channelGroupId: row.channelGroupId,
    createTime: row.createTime,
    updateTime: row.updateTime,
    addIndex: row.addIndex,
    maxMember: row.maxMember,
    expireTime: row.expireTime,
    workspaceId: row.workspaceId,
    mode: row.mode,
    redpacketPlay: row.redpacketPlay,
    topic: row.topic,
    rp: row.rp,
  );

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

  GroupsCompanion _toCompanion(Group group) => GroupsCompanion(
    id: Value(group.id),
    userJoinDate: Value(group.userJoinDate),
    name: Value(group.name),
    profile: Value(group.profile),
    icon: Value(group.icon),
    iconGaussian: Value(group.iconGaussian),
    permission: Value(group.permission),
    admin: Value(group.admin),
    members: Value(group.members),
    owner: Value(group.owner),
    admins: Value(group.admins),
    visible: Value(group.visible),
    speakInterval: Value(group.speakInterval),
    groupType: Value(group.groupType),
    roomType: Value(group.roomType),
    maxNumber: Value(group.maxNumber),
    channelId: Value(group.channelId),
    channelGroupId: Value(group.channelGroupId),
    createTime: Value(group.createTime),
    updateTime: Value(group.updateTime),
    addIndex: Value(group.addIndex),
    maxMember: Value(group.maxMember),
    expireTime: Value(group.expireTime),
    workspaceId: Value(group.workspaceId),
    mode: Value(group.mode),
    redpacketPlay: Value(group.redpacketPlay),
    topic: Value(group.topic),
    rp: Value(group.rp),
  );

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

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

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

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

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

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

  @override
  Future<List<Group>> getByWorkspace(int workspaceId) async {
    final rows = await _storage.selectWhere<DriftGroup, $GroupsTable>(
      (t) => t.workspaceId.equals(workspaceId),
    );
    return rows.map(_toEntity).toList();
  }

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

  @override
  Future<void> insertOrReplace(Group group) async {
    await _storage.insertOrReplace<DriftGroup>(_toCompanion(group));
  }

  @override
  Future<void> insertOrReplaceAll(List<Group> groups) async {
    await _storage.batchInsertOrReplace<DriftGroup>(
      groups.map(_toCompanion).toList(),
    );
  }

  @override
  Future<void> update(Group group) async {
    await _storage.updateWhere<DriftGroup, $GroupsTable>(
      _toCompanion(group),
      (t) => t.id.equals(group.id),
    );
  }

  @override
  Future<void> updateBatch(List<Group> groups) async {
    for (final group in groups) {
      await _storage.updateWhere<DriftGroup, $GroupsTable>(
        _toCompanion(group),
        (t) => t.id.equals(group.id),
      );
    }
  }

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

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

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