use crate::database::{article::Article, PsqlData};
use askama::Template;
use axum::{
    extract::{Extension, Path},
    http::StatusCode,
    response::IntoResponse,
    routing::{get, Router},
};
use sqlx::PgPool;
use std::{collections::HashMap, error::Error};

use super::{get_page, AppState, ArticleTemplate, HtmlTemplate};

pub fn get_router() -> Router {
    Router::new()
        .route("/", get(blog))
        .route("/:article", get(article))
}

async fn blog(state: Extension<AppState>) -> Result<impl IntoResponse, StatusCode> {
    get_page(&state.db, "blog").await
}

#[derive(Template)]
#[template(path = "blog_footer.html")]
struct BlogFooterTemplate {
    previous: String,
    next: String,
}

async fn article(
    state: Extension<AppState>,
    Path(params): Path<HashMap<String, String>>,
) -> Result<impl IntoResponse, StatusCode> {
    let db_pool = &state.db;
    let article_id: &String = params.get("article").unwrap();
    let article: Article = match Article::read_by_reference(db_pool, article_id).await {
        Ok(a) => *a,
        Err(_) => return Err(StatusCode::NOT_FOUND),
    };
    let footer = BlogFooterTemplate {
        previous: match article.previous {
            Some(a) => a,
            None => "".to_string(),
        },
        next: match article.next {
            Some(a) => a,
            None => "".to_string(),
        },
    };
    let template = ArticleTemplate {
        content: article.content,
        footer: footer.to_string(),
    };
    Ok(HtmlTemplate(template))
}

pub async fn get_articles_as_links_list(pool: &PgPool) -> Result<Vec<String>, Box<dyn Error>> {
    let mut articles: Vec<Article> = match Article::read_all(pool).await {
        Ok(a) => a.iter().map(|x| *x.clone()).collect(),
        Err(_) => Vec::new(),
    };

    articles.sort_by(|a, b| b.date.cmp(&a.date));

    let list: Vec<String> = articles
        .iter()
        .map(|article| {
            format!(
                "<li><a href=\"/blog/{}\">{}</a></li>",
                article.reference, article.title
            )
        })
        .collect();
    Ok(list)
}
