use crate::{filters, utils::ApplicationError};
use actix_web::{web, HttpResponse, Responder};
use chrono::{NaiveDate, Utc};
use rinja::Template;
use serde::Deserialize;
use sqlx::PgPool;

use crate::models::{Area, Availabillity, Event, Role, User};

#[derive(Deserialize)]
pub struct CalendarQuery {
    date: Option<NaiveDate>,
    area: Option<i32>,
}

#[derive(Template)]
#[template(path = "index.html")]
struct CalendarTemplate {
    user: User,
    date: NaiveDate,
    selected_area: Option<i32>,
    areas: Vec<Area>,
    events: Vec<Event>,
    availabillities: Vec<Availabillity>,
}

#[actix_web::get("/")]
async fn get(
    user: web::ReqData<User>,
    pool: web::Data<PgPool>,
    query: web::Query<CalendarQuery>,
) -> Result<impl Responder, ApplicationError> {
    let date = match query.date {
        Some(given_date) => given_date,
        None => Utc::now().date_naive(),
    };

    let areas = Area::read_all(pool.get_ref()).await?;

    let selected_area = match query.area {
        Some(id) => {
            if !areas.iter().any(|a| a.id == id) {
                return Ok(HttpResponse::BadRequest().finish());
            }

            Some(id)
        }
        None => None,
    };

    let events = Event::read_all_by_date_and_area_including_location(
        pool.get_ref(),
        date,
        query.area.unwrap_or(user.area_id),
    )
    .await?;

    let availabillities = Availabillity::read_by_date_and_area_including_user(
        pool.get_ref(),
        date,
        query.area.unwrap_or(user.area_id),
    )
    .await?;

    let template = CalendarTemplate {
        user: user.into_inner(),
        date,
        selected_area,
        areas,
        events,
        availabillities,
    };

    Ok(HttpResponse::Ok().body(template.render()?))
}
