use std::collections::HashSet;

use crate::gobject_models::{GArticle, GArticleID};
use news_flash::NewsFlash;
use news_flash::models::{Enclosure, FatArticle, Feed, Tag, TagID};

#[derive(Debug, Clone)]
pub struct ArticleLoader {
    article: FatArticle,
    feed: Option<Feed>,
    enclosures: Vec<Enclosure>,
    tags: Vec<Tag>,
}

impl ArticleLoader {
    pub fn load(article_id: &GArticleID, news_flash: &NewsFlash) -> Option<Self> {
        let Ok(fat_article) = news_flash.get_fat_article(article_id.as_ref()) else {
            return None;
        };

        let enclosures = news_flash.get_enclosures(article_id.as_ref()).unwrap_or_default();

        let (tags, taggings) = news_flash.get_tags().unwrap_or_default();
        let taggings: HashSet<&TagID> = taggings
            .iter()
            .filter(|t| &t.article_id == article_id.as_ref())
            .map(|t| &t.tag_id)
            .collect();
        let tags = tags
            .into_iter()
            .filter(|t| taggings.contains(&t.tag_id))
            .collect::<Vec<_>>();

        let feed = news_flash
            .get_feeds()
            .ok()
            .and_then(|(feeds, _)| feeds.into_iter().find(|f| f.feed_id == fat_article.feed_id));

        Some(Self {
            article: fat_article,
            feed,
            enclosures,
            tags,
        })
    }

    pub fn build(self) -> GArticle {
        GArticle::from_fat_article(self.article, self.feed.as_ref(), self.tags, self.enclosures)
    }
}
