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

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

  ChatBotRepositoryImpl(this._storage);

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

  ChatBot _toEntity(DriftChatBot row) => ChatBot(
    id: row.id,
    name: row.name,
    username: row.username,
    botUserId: row.botUserId,
    icon: row.icon,
    iconGaussian: row.iconGaussian,
    description: row.description,
    token: row.token,
    flag: row.flag,
    status: row.status,
    webhook: row.webhook,
    commands: row.commands,
    banner: row.banner,
    channelId: row.channelId,
    channelGroupId: row.channelGroupId,
    deletedAt: row.deletedAt,
    internalWebhook: row.internalWebhook,
    mode: row.mode,
    redirectUrl: row.redirectUrl,
    isInvitable: row.isInvitable,
    isAllowForward: row.isAllowForward,
    tips: row.tips,
  );

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

  ChatBotsCompanion _toCompanion(ChatBot chatBot) => ChatBotsCompanion(
    id: Value(chatBot.id),
    name: Value(chatBot.name),
    username: Value(chatBot.username),
    botUserId: Value(chatBot.botUserId),
    icon: Value(chatBot.icon),
    iconGaussian: Value(chatBot.iconGaussian),
    description: Value(chatBot.description),
    token: Value(chatBot.token),
    flag: Value(chatBot.flag),
    status: Value(chatBot.status),
    webhook: Value(chatBot.webhook ?? ''),
    commands: Value(chatBot.commands ?? '[]'),
    banner: Value(chatBot.banner),
    channelId: Value(chatBot.channelId),
    channelGroupId: Value(chatBot.channelGroupId),
    deletedAt: Value(chatBot.deletedAt),
    internalWebhook: Value(chatBot.internalWebhook),
    mode: Value(chatBot.mode),
    redirectUrl: Value(chatBot.redirectUrl),
    isInvitable: Value(chatBot.isInvitable),
    isAllowForward: Value(chatBot.isAllowForward),
    tips: Value(chatBot.tips),
  );

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

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

  @override
  Stream<ChatBot?> watchChatBot(int id) {
    return _storage
        .watchFirst<DriftChatBot, $ChatBotsTable>((t) => t.id.equals(id))
        .map((row) => row != null ? _toEntity(row) : null);
  }

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

  @override
  Future<List<ChatBot>> getChatBots({int? limit}) async {
    if (limit != null) {
      final rows = await _storage.rawQuery('SELECT * FROM chat_bot LIMIT ?', [
        limit,
      ]);
      return rows
          .map(
            (row) => ChatBot(
              id: row.read<int>('id'),
              name: row.readNullable<String>('name'),
              username: row.readNullable<String>('username'),
              botUserId: row.readNullable<int>('bot_user_id'),
              icon: row.readNullable<String>('icon'),
              iconGaussian: row.readNullable<String>('icon_gaussian'),
              description: row.readNullable<String>('description'),
              token: row.readNullable<String>('token'),
              flag: row.readNullable<int>('flag'),
              status: row.readNullable<int>('status'),
              webhook: row.readNullable<String>('webhook'),
              commands: row.readNullable<String>('commands'),
              banner: row.readNullable<String>('banner'),
              channelId: row.readNullable<int>('channel_id'),
              channelGroupId: row.readNullable<int>('channel_group_id'),
              deletedAt: row.readNullable<int>('deleted_at'),
              internalWebhook: row.readNullable<String>('internal_webhook'),
              mode: row.readNullable<int>('mode'),
              redirectUrl: row.readNullable<String>('redirect_url'),
              isInvitable: row.readNullable<int>('is_invitable'),
              isAllowForward: row.readNullable<int>('is_allow_forward'),
              tips: row.readNullable<String>('tips'),
            ),
          )
          .toList();
    }

    final rows = await _storage.selectAll<DriftChatBot>();
    return rows.map(_toEntity).toList();
  }

  @override
  Future<ChatBot?> getChatBot(int id) async {
    final row = await _storage.selectFirst<DriftChatBot, $ChatBotsTable>(
      (t) => t.id.equals(id),
    );
    return row != null ? _toEntity(row) : null;
  }

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

  @override
  Future<void> insertOrReplaceChatBot(ChatBot chatBot) async {
    await _storage.insertOrReplace<DriftChatBot>(_toCompanion(chatBot));
  }

  @override
  Future<void> insertOrReplaceChatBots(List<ChatBot> chatBots) async {
    await _storage.batchInsertOrReplace<DriftChatBot>(
      chatBots.map(_toCompanion).toList(),
    );
  }

  @override
  Future<void> updateChatBot(ChatBot chatBot) async {
    await _storage.updateWhere<DriftChatBot, $ChatBotsTable>(
      _toCompanion(chatBot),
      (t) => t.id.equals(chatBot.id),
    );
  }

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

  @override
  Future<void> deleteChatBot(int id) async {
    await _storage.deleteWhere<DriftChatBot, $ChatBotsTable>(
      (t) => t.id.equals(id),
    );
  }

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