use crate::controllers::posts;
use crate::misc::get_context;
use crate::models::NewPost;
use rocket::http::{Cookie, Cookies};
use rocket::request::Form;
use rocket::response::Redirect;
use rocket::Route;
use rocket_contrib::templates::Template;
use std::env;
use std::vec::Vec;

#[derive(FromForm)]
struct Login {
    username: String,
    password: String,
}

#[get("/")]
fn index(mut cookies: Cookies<'_>) -> Result<Redirect, Template> {
    let password = env::var("admin_pass").expect("admin_pass not setted");
    match cookies.get_private("user") {
        Some(cookie) => {
            if cookie.value() == password {
                Ok(Redirect::to("/admin/panel"))
            } else {
                let context = get_context();

                Err(Template::render("admin/index", context))
            }
        }
        None => {
            let context = get_context();

            Err(Template::render("admin/index", context))
        }
    }
}

#[post("/", data = "<login>")]
fn login(mut cookies: Cookies<'_>, login: Form<Login>) -> Redirect {
    let username = env::var("admin_user").expect("admin_user not setted");
    let password = env::var("admin_pass").expect("admin_pass not setted");

    if login.username == username && login.password == password {
        cookies.add_private(Cookie::new("user", password));
        Redirect::to("/admin/panel")
    } else {
        Redirect::to("/admin")
    }
}

#[get("/panel")]
fn panel(mut cookies: Cookies<'_>) -> Result<Template, Redirect> {
    let password = env::var("admin_pass").expect("admin_pass not setted");

    match cookies.get_private("user") {
        Some(cookie) => {
            if cookie.value() == password {
                let mut context = get_context();

                let (all_posts, n_posts) = posts::get_posts(None);

                context.insert("posts", &all_posts);
                context.insert("n_posts", &n_posts);
                Ok(Template::render("admin/panel", context))
            } else {
                Err(Redirect::to("/admin"))
            }
        }
        None => Err(Redirect::to("/admin")),
    }
}

#[get("/add_post")]
fn add_post(mut cookies: Cookies<'_>) -> Result<Template, Redirect> {
    let password = env::var("admin_pass").expect("admin_pass not setted");

    match cookies.get_private("user") {
        Some(cookie) => {
            if cookie.value() == password {
                let context = get_context();

                Ok(Template::render("admin/add_post", context))
            } else {
                Err(Redirect::to("/admin"))
            }
        }
        None => Err(Redirect::to("/admin")),
    }
}

#[post("/add_post", data = "<post>")]
fn write_add_post(mut cookies: Cookies<'_>, post: Form<NewPost>) -> Redirect {
    let password = env::var("admin_pass").expect("admin_pass not setted");

    match cookies.get_private("user") {
        Some(cookie) => {
            if cookie.value() == password {
                match posts::add_post(&post) {
                    Ok(post) => Redirect::to(format!("/post/{}", post.id)),
                    Err(_) => Redirect::to("admin/add_post"),
                }
            } else {
                Redirect::to("/admin")
            }
        }
        None => Redirect::to("/admin"),
    }
}

#[get("/edit_post/<id>")]
fn edit_post(mut cookies: Cookies<'_>, id: i32) -> Result<Template, Redirect> {
    let password = env::var("admin_pass").expect("admin_pass not setted");

    match cookies.get_private("user") {
        Some(cookie) => {
            if cookie.value() == password {
                let mut context = get_context();

                let post = posts::get_post(id).unwrap();

                context.insert("id", &post.id);
                context.insert("title", &post.title);
                context.insert("content", &post.content);
                context.insert("published", &post.published);

                Ok(Template::render("admin/edit_post", context))
            } else {
                Err(Redirect::to("/admin"))
            }
        }
        None => Err(Redirect::to("/admin")),
    }
}

#[post("/edit_post/<id>", data = "<post>")]
fn write_edit_post(mut cookies: Cookies<'_>, id: i32, post: Form<NewPost>) -> Redirect {
    let password = env::var("admin_pass").expect("admin_pass not setted");

    match cookies.get_private("user") {
        Some(cookie) => {
            if cookie.value() == password {
                match posts::edit_post(id, &post) {
                    Ok(post) => Redirect::to(format!("/post/{}", post.id)),
                    Err(_) => Redirect::to("admin/edit_post"),
                }
            } else {
                Redirect::to("/admin")
            }
        }
        None => Redirect::to("/admin"),
    }
}

pub fn get_routes() -> Vec<Route> {
    routes![
        index,
        login,
        panel,
        add_post,
        write_add_post,
        edit_post,
        write_edit_post
    ]
}