use crate::structs::{AppSettings, ContentOrRedirect};
use crate::utils::json_responses::make_bad_json_data_response;
use crate::utils::response::not_ok_json_response;
use rocket::http::{CookieJar, Status};
use rocket::response::Redirect;
use rocket::{get, State};

/// *`GET /auth-token/<token_key>/<code>/<client_code>`*
///
/// Typically mounted as **`/settings/auth-token/<token_key>/<code>/<client_code>`**
///
/// A landing URL for authentification via a gateway server.
///
/// `token_key` is the auth gateway label.
///
/// `code` is the code returned by that server, for future requests
///
/// `client_code` is a code generated by pankosmia-web to show that the incoming request corresponds to an earlier auth request.
///
/// A cookie called `<token_key>_code` is set on successful authentication.
#[get("/auth-token/<token_key>/<code>/<client_code>")]
pub fn get_new_auth_token<'a>(
    state: &State<AppSettings>,
    token_key: String,
    code: String,
    client_code: String,
    cj: &CookieJar<'_>,
) -> ContentOrRedirect {
    if !state.gitea_endpoints.contains_key(&token_key) {
        return ContentOrRedirect::Content(not_ok_json_response(
            Status::BadRequest,
            make_bad_json_data_response(format!("Unknown GITEA endpoint name: {}", token_key)),
        ));
    }
    let mut auth_requests = state.auth_requests.lock().unwrap();
    if !auth_requests.contains_key(&token_key) {
        return ContentOrRedirect::Content(not_ok_json_response(
            Status::BadRequest,
            make_bad_json_data_response(format!("No record auth request found for {}", token_key)),
        ));
    };
    let auth_request_record = auth_requests.get(&token_key).unwrap();
    if auth_request_record.code != client_code {
        return ContentOrRedirect::Content(not_ok_json_response(
            Status::BadRequest,
            make_bad_json_data_response(format!("Invalid client code for {}", token_key)),
        ));
    }
    let redirect_uri = format!("/{}", auth_request_record.redirect_uri.clone());
    auth_requests.remove(&token_key);
    let mut tokens_inner = state.auth_tokens.lock().unwrap();
    if code == "" {
        cj.remove(format!("{}_code", token_key.clone()));
        tokens_inner.remove(&token_key);
    } else {
        tokens_inner.insert(token_key.clone(), code.clone());
        cj.add((format!("{}_code", token_key), code));
    }
    ContentOrRedirect::Redirect(Redirect::to(redirect_uri))
}
