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

/// 聊天仓储实现
///
/// ## 职责
/// - 所有 DB 操作通过 [StorageSdkApi]，不直接接触 AppDatabase
/// - DriftChat ↔ Domain Chat 映射
/// - 所有公开接口只接受 Domain 实体，Companion 转换完全内聚在此类
///
/// ## 数据流
/// ```
/// 网络：Chat.fromJson(json) → insertOrReplaceChat(chat) → StorageSdkApi → DB
/// 监听：StorageSdkApi.watchAll → DriftChat → _toEntity() → UI
/// ```
class ChatRepositoryImpl implements ChatRepository {
  final StorageSdkApi _storage;

  ChatRepositoryImpl(this._storage);

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

  Chat _toEntity(DriftChat row) => Chat(
    id: row.id,
    typ: row.typ,
    lastId: row.lastId,
    lastTyp: row.lastTyp,
    lastMsg: row.lastMsg,
    lastTime: row.lastTime,
    lastPos: row.lastPos,
    firstPos: row.firstPos,
    msgIdx: row.msgIdx,
    profile: row.profile,
    pin: row.pin,
    icon: row.icon,
    iconGaussian: row.iconGaussian,
    name: row.name,
    userId: row.userId,
    chatId: row.chatId,
    friendId: row.friendId,
    sort: row.sort,
    unreadNum: row.unreadNum,
    unreadCount: row.unreadCount,
    hideChatMsgIdx: row.hideChatMsgIdx,
    readChatMsgIdx: row.readChatMsgIdx,
    otherReadIdx: row.otherReadIdx,
    unreadAtMsgIdx: row.unreadAtMsgIdx,
    deleteTime: row.deleteTime,
    addIndex: row.addIndex,
    flag: row.flag,
    flagMy: row.flagMy,
    autoDeleteInterval: row.autoDeleteInterval,
    mute: row.mute,
    verified: row.verified,
    createTime: row.createTime,
    startIdx: row.startIdx,
    isReadMsg: row.isReadMsg,
    translateOutgoing: row.translateOutgoing,
    translateIncoming: row.translateIncoming,
    incomingIdx: row.incomingIdx,
    outgoingIdx: row.outgoingIdx,
    incomingSoundId: row.incomingSoundId,
    outgoingSoundId: row.outgoingSoundId,
    notificationSoundId: row.notificationSoundId,
    chatKey: row.chatKey,
    activeChatKey: row.activeChatKey,
    coverIdx: row.coverIdx,
    round: row.round,
    workspaceId: row.workspaceId,
    localPermission: row.localPermission,
  );

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

  ChatsCompanion _toCompanion(Chat chat) => ChatsCompanion(
    id: Value(chat.id),
    typ: Value(chat.typ),
    lastId: Value(chat.lastId),
    lastTyp: Value(chat.lastTyp),
    lastMsg: Value(chat.lastMsg),
    lastTime: Value(chat.lastTime),
    lastPos: Value(chat.lastPos),
    firstPos: Value(chat.firstPos),
    msgIdx: Value(chat.msgIdx),
    profile: Value(chat.profile),
    pin: Value(chat.pin),
    icon: Value(chat.icon),
    iconGaussian: Value(chat.iconGaussian),
    name: Value(chat.name),
    userId: Value(chat.userId),
    chatId: Value(chat.chatId),
    friendId: Value(chat.friendId),
    sort: Value(chat.sort),
    unreadNum: Value(chat.unreadNum),
    unreadCount: Value(chat.unreadCount),
    hideChatMsgIdx: Value(chat.hideChatMsgIdx),
    readChatMsgIdx: Value(chat.readChatMsgIdx),
    otherReadIdx: Value(chat.otherReadIdx),
    unreadAtMsgIdx: Value(chat.unreadAtMsgIdx),
    deleteTime: Value(chat.deleteTime),
    addIndex: Value(chat.addIndex),
    flag: Value(chat.flag),
    flagMy: Value(chat.flagMy),
    autoDeleteInterval: Value(chat.autoDeleteInterval),
    mute: Value(chat.mute),
    verified: Value(chat.verified),
    createTime: Value(chat.createTime),
    startIdx: Value(chat.startIdx),
    isReadMsg: Value(chat.isReadMsg),
    translateOutgoing: Value(chat.translateOutgoing),
    translateIncoming: Value(chat.translateIncoming),
    incomingIdx: Value(chat.incomingIdx),
    outgoingIdx: Value(chat.outgoingIdx),
    incomingSoundId: Value(chat.incomingSoundId),
    outgoingSoundId: Value(chat.outgoingSoundId),
    notificationSoundId: Value(chat.notificationSoundId),
    chatKey: Value(chat.chatKey),
    activeChatKey: Value(chat.activeChatKey),
    coverIdx: Value(chat.coverIdx),
    round: Value(chat.round),
    workspaceId: Value(chat.workspaceId),
    localPermission: Value(chat.localPermission),
  );

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

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

  @override
  Stream<Chat?> watchChat(int id) {
    return _storage
        .watchFirst<DriftChat, $ChatsTable>((t) => t.id.equals(id))
        .map((row) => row != null ? _toEntity(row) : null);
  }

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

  @override
  Future<List<Chat>> getChats() async {
    final rows = await _storage.selectAll<DriftChat>();
    return rows.map(_toEntity).toList();
  }

  @override
  Future<Chat?> getChat(int id) async {
    final row = await _storage.selectFirst<DriftChat, $ChatsTable>(
      (t) => t.id.equals(id),
    );
    return row != null ? _toEntity(row) : null;
  }

  @override
  Future<List<Chat>> getChatsPage({
    required int offset,
    required int limit,
  }) async {
    final rows = await _storage.rawQuery(
      'SELECT * FROM chat ORDER BY id LIMIT ? OFFSET ?',
      [limit, offset],
    );
    return rows
        .map(
          (row) => Chat(
            id: row.read<int>('id'),
            typ: row.readNullable<int>('typ'),
            lastId: row.readNullable<int>('last_id'),
            lastTyp: row.readNullable<int>('last_typ'),
            lastMsg: row.readNullable<String>('last_msg'),
            lastTime: row.readNullable<int>('last_time'),
            lastPos: row.read<int>('last_pos'),
            firstPos: row.read<int>('first_pos'),
            msgIdx: row.readNullable<int>('msg_idx'),
            profile: row.readNullable<String>('profile'),
            pin: row.readNullable<String>('pin'),
            icon: row.readNullable<String>('icon'),
            iconGaussian: row.read<String>('icon_gaussian'),
            name: row.readNullable<String>('name'),
            userId: row.readNullable<int>('user_id'),
            chatId: row.readNullable<int>('chat_id'),
            friendId: row.readNullable<int>('friend_id'),
            sort: row.readNullable<int>('sort'),
            unreadNum: row.readNullable<int>('unread_num'),
            unreadCount: row.readNullable<int>('unread_count'),
            hideChatMsgIdx: row.readNullable<int>('hide_chat_msg_idx'),
            readChatMsgIdx: row.readNullable<int>('read_chat_msg_idx'),
            otherReadIdx: row.readNullable<int>('other_read_idx'),
            unreadAtMsgIdx: row.readNullable<String>('unread_at_msg_idx'),
            deleteTime: row.readNullable<int>('delete_time'),
            addIndex: row.readNullable<int>('add_index'),
            flag: row.read<int>('flag'),
            flagMy: row.readNullable<int>('flag_my'),
            autoDeleteInterval: row.readNullable<int>('auto_delete_interval'),
            mute: row.readNullable<int>('mute'),
            verified: row.readNullable<int>('verified'),
            createTime: row.readNullable<int>('create_time'),
            startIdx: row.readNullable<int>('start_idx'),
            isReadMsg: row.readNullable<int>('is_read_msg'),
            translateOutgoing: row.read<String>('translate_outgoing'),
            translateIncoming: row.read<String>('translate_incoming'),
            incomingIdx: row.read<int>('incoming_idx'),
            outgoingIdx: row.read<int>('outgoing_idx'),
            incomingSoundId: row.read<int>('incoming_sound_id'),
            outgoingSoundId: row.read<int>('outgoing_sound_id'),
            notificationSoundId: row.read<int>('notification_sound_id'),
            chatKey: row.read<String>('chat_key'),
            activeChatKey: row.read<String>('active_chat_key'),
            coverIdx: row.read<int>('cover_idx'),
            round: row.read<int>('round'),
            workspaceId: row.read<int>('workspace_id'),
            localPermission: row.read<int>('local_permission'),
          ),
        )
        .toList();
  }

  @override
  Future<int> countChats() async {
    return _storage.count<DriftChat, $ChatsTable>();
  }

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

  @override
  Future<void> insertOrReplaceChat(Chat chat) async {
    await _storage.insertOrReplace<DriftChat>(_toCompanion(chat));
  }

  @override
  Future<void> insertOrReplaceChats(List<Chat> chats) async {
    await _storage.batchInsertOrReplace<DriftChat>(
      chats.map(_toCompanion).toList(),
    );
  }

  @override
  Future<void> updateChat(Chat chat) async {
    await _storage.updateWhere<DriftChat, $ChatsTable>(
      _toCompanion(chat),
      (t) => t.id.equals(chat.id),
    );
  }

  @override
  Future<void> updateChatsBatch(List<Chat> chats) async {
    for (final chat in chats) {
      await _storage.updateWhere<DriftChat, $ChatsTable>(
        _toCompanion(chat),
        (t) => t.id.equals(chat.id),
      );
    }
  }

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

  @override
  Future<void> deleteChat(int id) async {
    await _storage.deleteWhere<DriftChat, $ChatsTable>((t) => t.id.equals(id));
  }

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