Skip to content
use actix_web::{
    App, HttpResponse, HttpServer, Responder, get,
    web::{self},
};
use db::Database;
use env_logger::Env;
use log::{info, warn};

mod assets;
mod auth;
mod config;
mod db;
mod view;

#[get("/health")]
async fn health() -> impl Responder {
    HttpResponse::Ok()
}

#[get("/up")]
async fn up() -> impl Responder {
    HttpResponse::Ok().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let config = config::from_env();

    let log_filter = format!(
        "{},libsql=warn,turso=warn,tracing::span=warn",
        config.log_level()
    );
    env_logger::Builder::from_env(Env::default().default_filter_or(log_filter)).init();

    info!("{config}");

    let config = web::Data::new(config);

    config.maybe_reset_database();

    let db_path = config.db_path().to_string();

    let db = Database::new(&db_path);

    let auth_state = web::Data::new(auth::NotesContext::new(db));

    {
        let auth_state = auth_state.clone();
        actix_web::rt::spawn(async move {
            loop {
                match auth_state.db().init_tables().await {
                    Ok(()) => {
                        info!("Database initialized successfully");
                        auth_state.set_initialized();
                        return;
                    }
                    Err(e) => {
                        warn!("Database init failed (will retry): {e}");
                        actix_web::rt::time::sleep(std::time::Duration::from_secs(1)).await;
                    }
                }
            }
        });
    }

    let bind_address = config.address();

    HttpServer::new(move || {
        App::new()
            .app_data(config.clone())
            .app_data(auth_state.clone())
            .service(health)
            .service(up)
            .service(assets::assets)
            .service(view::auth::login_page)
            .service(auth::handlers::login_handler)
            .service(auth::handlers::logout_handler)
            .service(auth::handlers::save_handler)
            .service(auth::handlers::search_handler)
            .service(auth::handlers::note_details_handler)
            .service(auth::handlers::edit_note_handler)
            .service(auth::handlers::delete_note_handler)
            .service(view::dashboard::index)
            .service(view::dashboard::save_page)
            .service(view::dashboard::view_page)
            .service(view::dashboard::search_card_handler)
    })
    .bind(bind_address)?
    .run()
    .await
}