import type { BlogPost } from './BlogPost.js';
import type { BookReview } from './BookReview.js';
import { MarkdownRepository } from './markdown-repository.js';

export interface BlogItem {
    title: string;
    date: string;
    content: string;
    slug: string;
    content_type: 'blog' | 'book_review' | 'snout_street_studios';
    tags?: string[];
}

export interface BlogPostListItem extends BlogItem {
    title: string;
    author: string;
    date: string;
    book_review: boolean;
    preview: string;
    tags: string[];
}

export interface BookReviewListItem extends BlogItem {
    book_review: true;
    title: string;
    author: string;
    image: string;
    slug: string;
    score: number;
    finished: string;
}

export class BlogController {
    private _markdownRepository: MarkdownRepository;

    static async singleton(): Promise<BlogController> {
        const markdownRepository = await MarkdownRepository.singleton();
        return new BlogController(markdownRepository);
    }

    constructor(markdownRepository: MarkdownRepository) {
        this._markdownRepository = markdownRepository;
    }

    get markdownRepository(): MarkdownRepository {
        return this._markdownRepository;
    }

    async createBlogPost(resolvedFileName: string, markdownContent: string): Promise<BlogPost> {
        const createdBlogPost = await this._markdownRepository.createBlogPostMarkdownFile(
            resolvedFileName,
            markdownContent
        );
        this._markdownRepository = await MarkdownRepository.singleton(true);
        return createdBlogPost;
    }

    async getAllBlogPosts(pageSize?: number): Promise<Array<BlogPostListItem | BookReviewListItem>> {
        const blogPosts = this._markdownRepository.blogPosts;

        const bookReviews = this._markdownRepository.bookReviews;

        const blogPostListItems: BlogPostListItem[] = blogPosts.blogPosts.map((blogPost) => {
            return this.blogPostToBlogPostListItem(blogPost);
        });

        const bookReviewListItems: BookReviewListItem[] = bookReviews.bookReviews.map((bookReview) => {
            return this.bookReviewToBookReviewListItem(bookReview);
        });

        const allBlogPosts = [...blogPostListItems, ...bookReviewListItems].sort((a, b) => (a.date > b.date ? -1 : 1));

        if (pageSize === undefined) {
            return allBlogPosts;
        }

        return allBlogPosts.slice(0, pageSize);
    }

    async getBlogPostBySlug(slug: string): Promise<BlogPostListItem | null> {
        const blogPost = this._markdownRepository.getBlogPostBySlug(slug);
        if (blogPost) {
            return this.blogPostToBlogPostListItem(blogPost);
        }

        return null;
    }

    async getBlogPostsByTags(tags: string[]): Promise<BlogPostListItem[]> {
        const posts = await this.getAllBlogPosts();
        const blogPosts = posts.filter((post) => post.content_type === 'blog') as BlogPostListItem[];
        return blogPosts
            .filter((post: BlogPostListItem) => post['tags']?.length > 0)
            .filter((post: BlogPostListItem) => (post.tags as string[]).some((tag) => tags.includes(tag)));
    }

    async getAnyKindOfContentBySlug(slug: string): Promise<BookReviewListItem | BlogPostListItem | null> {
        const blogPost = this._markdownRepository.getBlogPostBySlug(slug);
        if (blogPost) {
            return this.blogPostToBlogPostListItem(blogPost);
        }

        const bookReview = this._markdownRepository.getBookReviewBySlug(slug);
        if (bookReview) {
            return this.bookReviewToBookReviewListItem(bookReview);
        }

        return null;
    }

    private bookReviewToBookReviewListItem(bookReview: BookReview): BookReviewListItem {
        return {
            book_review: true,
            title: bookReview.title,
            author: bookReview.author,
            date: bookReview.date.toISOString(),
            finished: bookReview.finished.toISOString(),
            image: bookReview.image,
            score: bookReview.score,
            slug: bookReview.slug,
            content: bookReview.html,
            content_type: 'book_review',
        };
    }

    private blogPostToBlogPostListItem(blogPost: BlogPost): BlogPostListItem {
        return {
            title: blogPost.title,
            author: blogPost.author,
            book_review: false,
            content: blogPost.html,
            date: blogPost.date.toISOString(),
            preview: blogPost.excerpt,
            slug: blogPost.slug,
            content_type: 'blog',
            tags: blogPost.tags,
        };
    }
}
