import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { FilterQuery, Model, Types } from 'mongoose';
import { ModerationStatus } from '../../common/enums/moderation-status.enum';
import { Follow, FollowDocument } from '../follows/schemas/follow.schema';
import { Post, PostDocument } from '../posts/schemas/post.schema';

@Injectable()
export class FeedRepository {
  constructor(
    @InjectModel(Post.name) private readonly postModel: Model<PostDocument>,
    @InjectModel(Follow.name) private readonly followModel: Model<FollowDocument>,
  ) {}

  async findFollowingIds(userId: string): Promise<string[]> {
    const rows = await this.followModel
      .find({ followerId: new Types.ObjectId(userId) })
      .select({ followingId: 1 })
      .lean()
      .exec();

    return rows.map((row) => row.followingId.toString());
  }

  async findCandidatePosts(
    filter: FilterQuery<PostDocument>,
    limit: number,
  ): Promise<PostDocument[]> {
    const activeFilter: FilterQuery<PostDocument> = {
      ...filter,
      isDeleted: { $ne: true },
      isArchived: { $ne: true },
      moderationStatus: { $ne: ModerationStatus.HIDDEN },
    };

    return this.postModel
      .find(activeFilter)
      .populate({
        path: 'authorId',
        select:
          'name username stageName avatar isVerified isDisabled isPrivate location latitude longitude musicGenres musicRoles favoriteInstruments favoriteMaqamat followersCount',
      })
      .sort({ createdAt: -1 })
      .limit(limit)
      .exec();
  }

  async findPopularCandidatePosts(
    filter: FilterQuery<PostDocument>,
    limit: number,
  ): Promise<PostDocument[]> {
    return this.postModel
      .find({
        ...filter,
        isDeleted: { $ne: true },
        isArchived: { $ne: true },
        moderationStatus: { $ne: ModerationStatus.HIDDEN },
      })
      .populate({
        path: 'authorId',
        select:
          'name username stageName avatar isVerified isDisabled isPrivate location latitude longitude musicGenres musicRoles favoriteInstruments favoriteMaqamat followersCount',
      })
      .sort({
        savesCount: -1,
        shareCount: -1,
        commentsCount: -1,
        likesCount: -1,
        createdAt: -1,
      })
      .limit(limit)
      .exec();
  }

  async findTrendingPublicPosts(
    filter: FilterQuery<PostDocument>,
    skip: number,
    limit: number,
  ): Promise<PostDocument[]> {
    return this.postModel
      .find({
        ...filter,
        isDeleted: { $ne: true },
        isArchived: { $ne: true },
        moderationStatus: { $ne: ModerationStatus.HIDDEN },
      })
      .populate({
        path: 'authorId',
        select: 'name username stageName avatar isVerified isDisabled isPrivate',
      })
      .sort({
        shareCount: -1,
        likesCount: -1,
        commentsCount: -1,
        savesCount: -1,
        viewCount: -1,
        playCount: -1,
        createdAt: -1,
      })
      .skip(skip)
      .limit(limit)
      .exec();
  }

  async count(filter: FilterQuery<PostDocument>): Promise<number> {
    return this.postModel
      .countDocuments({
        ...filter,
        isDeleted: { $ne: true },
        isArchived: { $ne: true },
        moderationStatus: { $ne: ModerationStatus.HIDDEN },
      })
      .exec();
  }
}
