import { Injectable } from '@nestjs/common';
import { FeedQueryDto } from '../feed/dto/feed-query.dto';
import { FeedService } from '../feed/feed.service';
import { SearchQueryDto } from '../search/dto/search-query.dto';
import { SearchService } from '../search/search.service';

export type MusicWorldCardType = 'search' | 'navigation';

export type MusicWorldCard = {
  key: string;
  title: string;
  subtitle: string;
  imageUrl: string | null;
  type: MusicWorldCardType;
  endpoint: string;
  query?: string;
};

export type MusicWorldSection = {
  key: string;
  title: string;
  endpoint: string;
};

export type MusicWorldResponse = {
  title: string;
  searchPlaceholder: string;
  cards: MusicWorldCard[];
  sections: MusicWorldSection[];
};

type ExploreGridItem = {
  id: string;
  postType: string;
  content: string;
  thumbnailUrl: string;
  displayUrl: string;
  media: Record<string, unknown>;
  author: {
    id: string;
    name: string;
    username: string;
    avatar: string;
    isVerified: boolean;
  };
  engagement: {
    likesCount: number;
    commentsCount: number;
    viewCount: number;
    playCount: number;
  };
  isLiked: boolean;
  isSaved: boolean;
  createdAt: unknown;
};

@Injectable()
export class MusicWorldService {
  constructor(
    private readonly feedService: FeedService,
    private readonly searchService: SearchService,
  ) {}

  getMusicWorld(): MusicWorldResponse {
    return {
      title: 'عالم الموسيقى',
      searchPlaceholder: 'شو حابب تلاقي اليوم؟',
      cards: [
        {
          key: 'oud',
          title: 'عود',
          subtitle: 'اكتشف عزف العود والمقامات الشرقية',
          imageUrl: '/uploads/music-world/oud.jpg',
          type: 'search',
          endpoint: '/api/v1/search/posts',
          query: 'عود',
        },
        {
          key: 'ney',
          title: 'ناي',
          subtitle: 'أجواء هادئة وروحانية',
          imageUrl: '/uploads/music-world/ney.jpg',
          type: 'search',
          endpoint: '/api/v1/search/posts',
          query: 'ناي',
        },
        {
          key: 'hijaz',
          title: 'مقام حجاز',
          subtitle: 'طابع شرقي مؤثر',
          imageUrl: '/uploads/music-world/hijaz.jpg',
          type: 'search',
          endpoint: '/api/v1/search/posts',
          query: 'مقام حجاز',
        },
        {
          key: 'levantine',
          title: 'موسيقى شامية',
          subtitle: 'اكتشف اللون الشامي',
          imageUrl: '/uploads/music-world/levantine.jpg',
          type: 'search',
          endpoint: '/api/v1/search/posts',
          query: 'موسيقى شامية',
        },
        {
          key: 'artists',
          title: 'فنانون',
          subtitle: 'اكتشف مبدعين موسيقيين',
          imageUrl: '/uploads/music-world/artists.jpg',
          type: 'navigation',
          endpoint: '/api/v1/users/discover',
        },
        {
          key: 'explore',
          title: 'اكتشف الموسيقى',
          subtitle: 'منشورات ومقاطع موسيقية',
          imageUrl: '/uploads/music-world/explore.jpg',
          type: 'navigation',
          endpoint: '/api/v1/feed/explore',
        },
      ],
      sections: [
        {
          key: 'trending',
          title: 'الأكثر رواجا',
          endpoint: '/api/v1/feed/trending',
        },
        {
          key: 'explore',
          title: 'اكتشف',
          endpoint: '/api/v1/feed/explore',
        },
        {
          key: 'artists',
          title: 'مبدعون موسيقيون',
          endpoint: '/api/v1/users/discover',
        },
      ],
    };
  }

  async getExplore(currentUserId: string, query: FeedQueryDto) {
    const feed = (await this.feedService.getExplore(currentUserId, query)) as Record<
      string,
      unknown
    >;
    const items = Array.isArray(feed.items)
      ? feed.items
          .filter((item): item is Record<string, unknown> => {
            return (
              typeof item === 'object' &&
              item !== null &&
              (item as Record<string, unknown>).feedItemType === 'post' &&
              !this.hasPrivateAuthor(item as Record<string, unknown>)
            );
          })
          .map((item) => this.toExploreGridItem(item))
      : [];

    return {
      items,
      count: items.length,
      page: feed.page,
      limit: feed.limit,
      total: feed.total,
      totalPages: feed.totalPages,
      nextCursor: feed.nextCursor ?? null,
      pagination: feed.pagination,
    };
  }

  async search(currentUserId: string, query: SearchQueryDto) {
    const posts = await this.searchService.searchPosts(currentUserId, {
      ...query,
      type: 'posts',
    });

    return {
      ...posts,
      items: posts.items
        .filter((item) => !this.hasPrivateAuthor(item as Record<string, unknown>))
        .map((item) => this.toExploreGridItem(item as Record<string, unknown>)),
    };
  }

  private toExploreGridItem(item: Record<string, unknown>): ExploreGridItem {
    const media = this.asRecord(item.media);
    const author = this.asRecord(item.authorId ?? item.author);
    const engagement = this.asRecord(item.engagement);
    const postType = String(item.postType ?? media.mediaType ?? '');
    const displayUrl = this.firstNonEmpty(
      media.displayUrl,
      item.displayUrl,
      this.resolveImageDisplayUrl(item),
      item.thumbnailUrl,
      media.thumbnailUrl,
    );
    const thumbnailUrl = this.firstNonEmpty(
      item.thumbnailUrl,
      media.thumbnailUrl,
      displayUrl,
      this.resolveImageDisplayUrl(item),
    );

    return {
      id: String(item.id ?? item._id ?? ''),
      postType,
      content: String(item.content ?? ''),
      thumbnailUrl,
      displayUrl,
      media,
      author: {
        id: String(author.id ?? author._id ?? ''),
        name: String(author.name ?? ''),
        username: String(author.username ?? ''),
        avatar: String(author.avatar ?? ''),
        isVerified: Boolean(author.isVerified),
      },
      engagement: {
        likesCount: Number(engagement.likesCount ?? item.likesCount ?? 0),
        commentsCount: Number(engagement.commentsCount ?? item.commentsCount ?? 0),
        viewCount: Number(engagement.viewCount ?? item.viewCount ?? 0),
        playCount: Number(engagement.playCount ?? item.playCount ?? 0),
      },
      isLiked: Boolean(item.isLiked ?? item.liked ?? item.likedByMe),
      isSaved: Boolean(item.isSaved ?? item.saved ?? item.savedByMe),
      createdAt: item.createdAt ?? null,
    };
  }

  private resolveImageDisplayUrl(item: Record<string, unknown>): string {
    const imageVariants = Array.isArray(item.imageVariants) ? item.imageVariants : [];
    const firstVariant = this.asRecord(imageVariants[0]);
    const imageItems = Array.isArray(item.imageItems) ? item.imageItems : [];
    const firstImageItem = this.asRecord(imageItems[0]);
    const imageUrls = Array.isArray(item.imageUrls) ? item.imageUrls : [];

    return this.firstNonEmpty(
      firstVariant.mediumUrl,
      firstVariant.highUrl,
      firstVariant.lowUrl,
      firstVariant.originalUrl,
      firstImageItem.url,
      imageUrls[0],
    );
  }

  private asRecord(value: unknown): Record<string, unknown> {
    return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {};
  }

  private hasPrivateAuthor(item: Record<string, unknown>): boolean {
    const author = this.asRecord(item.authorId ?? item.author);
    return author.isPrivate === true;
  }

  private firstNonEmpty(...values: unknown[]): string {
    return (
      values.find(
        (value): value is string => typeof value === 'string' && value.trim().length > 0,
      ) ?? ''
    );
  }
}
