use actix_web::http::header;
use actix_web::{cookie, web, HttpRequest, HttpResponse};

use crate::pages::templates::COOKIES_POLICY;
use crate::pages::{insert_security_headers, request_to_jar};
use crate::WebData;

#[derive(serde_derive::Serialize)]
struct CookieInfo {
    i_accept_cookie: bool,
}

pub async fn cookies_policy(request: HttpRequest, data: web::Data<WebData<'_>>) -> HttpResponse {
    let jar = request_to_jar(request);
    let body = match data.handlebars.render(
        COOKIES_POLICY,
        &CookieInfo {
            i_accept_cookie: jar
                .private(&data.cookies_key)
                .get("i_accept_cookie")
                .map_or(false, |x| x.value() == "yes"),
        },
    ) {
        Ok(b) => b,
        Err(e) => {
            log::error!("Render index error: {}", e);
            return HttpResponse::ServiceUnavailable().body(actix_web::body::None::new());
        }
    };
    insert_security_headers(HttpResponse::Ok()).body(body)
}

pub async fn post_accept_cookies(
    request: HttpRequest,
    data: web::Data<WebData<'_>>,
) -> HttpResponse {
    let mut jar = request_to_jar(request);
    let mut builder = cookie::Cookie::build("i_accept_cookie", "yes")
        .path("/")
        .secure(true)
        .http_only(true)
        .same_site(cookie::SameSite::Strict)
        .max_age(cookie::time::Duration::weeks(4));
    if data.set_cookie_domain {
        builder = builder.domain(data.base_domain.to_string());
    }
    jar.private_mut(&data.cookies_key).add(builder.finish());
    let mut response = HttpResponse::Found()
        .append_header((header::LOCATION, "cookies-policy.html"))
        .finish();
    if let Some(c) = jar.get("i_accept_cookie") {
        if let Err(e) = response.add_cookie(c) {
            log::error!("Cann't set cookie {}", e);
        }
    }
    response
}

pub async fn post_remove_cookies(data: web::Data<WebData<'_>>) -> HttpResponse {
    let mut response = HttpResponse::Found()
        .append_header((header::LOCATION, "cookies-policy.html"))
        .finish();
    let mut builder = cookie::Cookie::build("i_accept_cookie", "").path("/");
    if data.set_cookie_domain {
        builder = builder.domain(data.base_domain.to_string());
    }
    if let Err(e) = response.add_removal_cookie(&builder.finish()) {
        log::error!("Cann't set cookie {}", e);
    }
    let mut builder = cookie::Cookie::build("auth", "").path("/");
    if data.set_cookie_domain {
        builder = builder.domain(data.base_domain.to_string());
    }
    if let Err(e) = response.add_removal_cookie(&builder.finish()) {
        log::error!("Cann't set cookie {}", e);
    }
    response
}