use std::ops::DerefMut;

use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};

#[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct Log {
    pub msg: String,
    pub created_at: NaiveDateTime,
}

impl Log {
    pub async fn create(db: &SqlitePool, msg: String) -> bool {
        sqlx::query!("INSERT INTO log(msg) VALUES (?)", msg,)
            .execute(db)
            .await
            .is_ok()
    }
    pub async fn create_with_tx(db: &mut Transaction<'_, Sqlite>, msg: String) -> bool {
        sqlx::query!("INSERT INTO log(msg) VALUES (?)", msg,)
            .execute(db.deref_mut())
            .await
            .is_ok()
    }

    async fn last(db: &SqlitePool) -> Vec<Log> {
        sqlx::query_as!(
            Log,
            "
SELECT msg, created_at
FROM log 
ORDER BY id DESC
LIMIT 1000
    "
        )
        .fetch_all(db)
        .await
        .unwrap()
    }

    pub async fn generate_feed(db: &SqlitePool) -> String {
        let mut ret = String::from(
            r#"<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Ruder App Admin Feed</title>
<link>app.rudernlinz.at</link>
<description>An RSS feed with activities from app.rudernlinz.at</description>"#,
        );
        for log in Self::last(db).await {
            let utc_time: DateTime<Utc> = Utc::from_utc_datetime(&Utc, &log.created_at);
            let local_time = utc_time.with_timezone(&Local);
            ret.push_str("<item><title>");
            ret.push_str(&format!("({}) {}", local_time, log.msg));
            ret.push_str("</title></item>");
        }
        ret.push_str("</channel>");
        ret.push_str("</rss>");
        ret.replace('\n', "")
    }

    pub async fn show(db: &SqlitePool) -> String {
        let mut ret = String::new();

        for log in Self::last(db).await {
            let utc_time: DateTime<Utc> = Utc::from_utc_datetime(&Utc, &log.created_at);
            let local_time = utc_time.with_timezone(&Local);
            ret.push_str(&format!("- {} - {}\n", local_time, log.msg));
        }

        ret
    }
}
