use actix_cors::Cors;
use actix_files::Files;
use actix_web::middleware;
use actix_web::web::Data;
use actix_web::{web::scope, App, HttpServer};
use log::info;

mod db;
mod jwt;
mod routes;
mod state;
mod types;
mod util;

use jwt::Authentication;
use routes::{get_comments, get_posts, login, new_comment, new_post, post_by_id, register};
use state::CaptchaState;
use state::ServerState;
use util::hex_string;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();

    let data = ServerState::new().await;
    let capt_db = CaptchaState::new();
    let auth = Authentication::new("secret".as_bytes());

    #[cfg(debug_assertions)]
    {
        for _ in 0..10 {
            let s = hex_string(10);
            info!("Adding captcha key: {}", &s);
            capt_db.capthca_db.lock().unwrap().insert(s);
        }
    }

    info!("Spinning up server on http://localhost:8080");
    HttpServer::new(move || {
        let cors = Cors::default()
            .allowed_origin("https://shitpost.se")
            .allowed_methods(vec!["GET", "POST"])
            .max_age(3600);

        // In debug mode, allow localhost
        #[cfg(debug_assertions)]
        let cors = cors.allowed_origin("http://localhost:8080");

        App::new()
            .wrap(cors)
            .wrap(middleware::Compress::default())
            .wrap(middleware::Logger::default())
            .wrap(middleware::NormalizePath::trim())
            .service(
                scope("/api")
                    .service(get_posts)
                    .service(new_post)
                    .service(new_comment)
                    .service(get_comments)
                    .service(post_by_id)
                    .service(login)
                    .service(register)
                    .app_data(Data::new(data.clone()))
                    .app_data(Data::new(capt_db.clone()))
                    .app_data(Data::new(auth.clone())),
            )
            .service(
                Files::new("/", "./public")
                    .index_file("index.html")
                    .default_handler(actix_files::NamedFile::open("./public/index.html").unwrap()),
            )
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}