use crate::ManagedRing;
use crate::db;
use crate::{LISTEN_ADDRESS, LISTEN_PORT};
use rocket::figment::Figment;
use rocket::fs::FileServer;
use rocket::{Config, State};
use rocket_cors::{AllowedOrigins, CorsOptions};
use rocket_dyn_templates::{Template, context};
mod invite;
mod manifest;
mod member;
use invite::invite_redeem;
use manifest::get_manifest;
use member::{member_rotate, member_standing, member_unenroll, member_validate};
use std::env;

#[get("/")]
async fn index(ring: &State<ManagedRing>) -> Template {
    let mut conn = db::get_db_connection().await.unwrap();
    // borrow inner state
    let ring = ring.inner();
    let members = ring.members(&mut conn).await.unwrap();
    Template::render("index", context! { ring, members })
}

// #[post("/member/enroll", format = "application/json", data = "<member>")]
// async fn member_enroll() {
//     unimplemented!();
// }

// #[get("/signing-keypair")]
// fn generate_signing_keypair_json() -> serde_json::Value {
//     json!(generate_signing_keypair())
// }

// #[get("/encryption-keypair")]
// fn generate_encryption_keypair_json() -> serde_json::Value {
//     json!(generate_encryption_keypair())
// }

pub async fn rocket(port: Option<usize>, address: Option<String>, ring: ManagedRing) {
    /*
    ADDRESS/PORT PRIORITIZATION

    Command Line > env var > default

    */
    let port = port.unwrap_or_else(|| {
        env::var("RINGSPACE_ROCKET_PORT")
            .unwrap_or(LISTEN_PORT.to_string())
            .parse::<usize>()
            .unwrap()
    });

    let address = address.unwrap_or_else(|| {
        env::var("RINGSPACE_ROCKET_ADDRESS").unwrap_or(LISTEN_ADDRESS.to_string())
    });

    let figment = Figment::from(rocket::Config::default())
        .merge((Config::PORT, port))
        .merge((Config::ADDRESS, address));

    let cors = CorsOptions::default()
        .allowed_origins(AllowedOrigins::all())
        .send_wildcard(true) // Sends Access-Control-Allow-Origin: *
        .to_cors()
        .expect("Failed to create CORS");
    let _ = rocket::build()
        .configure(figment)
        .manage(ring)
        .attach(cors)
        .attach(Template::fairing())
        .mount("/", routes![index])
        .mount("/public", FileServer::from("static"))
        .mount("/api", routes![get_manifest])
        .mount("/api", routes![invite_redeem])
        .mount("/api", routes![member_standing])
        .mount("/api", routes![member_validate])
        .mount("/api", routes![member_rotate])
        .mount("/api", routes![member_unenroll])
        .launch()
        .await;
}
