import 'package:drift/drift.dart';
import 'package:sendtrain/database/database.dart';

part 'media_items_dao.g.dart';

@DriftAccessor(tables: [MediaItems])
class MediaItemsDao extends DatabaseAccessor<AppDatabase>
    with _$MediaItemsDaoMixin {
  MediaItemsDao(super.db);

  Future createOrUpdate(MediaItemsCompanion mediaItem) =>
      into(mediaItems).insertOnConflictUpdate(mediaItem);

  Future<List<MediaItem>> all() async {
    return await select(mediaItems).get();
  }

  Future<MediaItem> find(int id) async {
    return await (select(mediaItems)
          ..where((mediaItem) => mediaItem.id.equals(id)))
        .getSingle();
  }

  Future<List<MediaItem>> fromActivity(Activity activity) async {
    final result = select(db.objectMediaItems).join(
      [
        innerJoin(
          db.mediaItems,
          db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId),
        ),
      ],
    )
      ..where(db.objectMediaItems.objectType.equals(ObjectType.activities.name))
      ..where(db.objectMediaItems.objectId.equals(activity.id));

    final mediaItems =
        (await result.get()).map((e) => e.readTable(db.mediaItems)).toList();

    return mediaItems;
  }

  Future<List<MediaItem>> fromSession(int sessionId) async {
    final result = select(db.objectMediaItems).join(
      [
        innerJoin(
          db.mediaItems,
          db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId),
        ),
      ],
    )
      ..where(db.objectMediaItems.objectType.equals(ObjectType.sessions.name))
      ..where(db.objectMediaItems.objectId.equals(sessionId));

    final mediaItems =
        (await result.get()).map((e) => e.readTable(db.mediaItems)).toList();

    return mediaItems;
  }

  Stream<List<MediaItem>> watchSessionMediaItems(int id) {
    final query = select(db.objectMediaItems).join(
      [
        innerJoin(
          db.mediaItems,
          db.mediaItems.id.equalsExp(db.objectMediaItems.mediaId),
        ),
      ],
    )
      ..where(db.objectMediaItems.objectType.equals(ObjectType.sessions.name))
      ..where(db.objectMediaItems.objectId.equals(id));

    return query.watch().map((rows) {
      final mediaItems = (rows).map((e) => e.readTable(db.mediaItems)).toList();

      return mediaItems;
    });
  }

  Future remove(MediaItem mediaItem) => delete(mediaItems).delete(mediaItem);
  Future removeAll(Iterable<int> mediaItemIds) {
    return (delete(mediaItems)..where((table) => table.id.isIn(mediaItemIds)))
        .go();
  }
}