use askama::Template;
use axum::extract::State;
use time::Date;

use crate::{sources, AppState};

#[derive(Template)]
#[template(path = "index.html")]
pub struct HomeTemplate {
    time_since: TimeSince,
}

pub struct TimeSince {
    days: i32,
}

impl TimeSince {
    fn from_interval(leak: &Date, now: &Date) -> Self {
        Self {
            days: now.to_julian_day() - leak.to_julian_day(),
        }
    }
}

#[axum::debug_handler]
pub async fn get(state: State<AppState>) -> HomeTemplate {
    let mut t = vec![];

    for source in sources::sources() {
        let url = source.url();

        let mut cache = state.0.get_cache.lock().await;
        let now = time::OffsetDateTime::now_utc();

        let needs_update = match cache.get(&url) {
            None => {
                tracing::info!("Value is not present in cache");
                true
            }
            Some((cached_time, _)) => {
                let other_day = cached_time.to_julian_day() != now.to_julian_day();
                let other_hour = cached_time.hour() != now.hour();

                if other_day {
                    tracing::info!("Value is from another day");
                }
                if other_hour {
                    tracing::info!("Value is from another hour");
                }

                other_day || other_hour
            }
        };

        if needs_update {
            tracing::info!("Need update cache");
            let Ok(res) = (reqwest::get(url.clone())).await else {
                tracing::error!("fetch error");
                continue;
            };

            let Ok(text) = res.text().await else {
                tracing::error!("fetch decode text error");
                continue;
            };

            tracing::info!("Cache updated");
            cache.insert(url.clone(), (now, text));
        }

        let Some((_, text)) = cache.get(&url) else {
            tracing::error!("filling cache error");
            continue;
        };

        let Ok(last) = source.latest_leak(text) else {
            tracing::error!("source decode error");
            continue;
        };

        t.push(last);
    }

    let last = t
        .into_iter()
        .max()
        .unwrap_or(time::Date::from_calendar_date(2021, time::Month::July, 14).unwrap());

    let now = time::OffsetDateTime::now_utc();
    let now = time::Date::from_calendar_date(now.year(), now.month(), now.day()).unwrap();

    HomeTemplate {
        time_since: TimeSince::from_interval(&last, &now),
    }
}
