use axum::http::{StatusCode, Uri};
use axum::response::IntoResponse;
use axum::routing::post;
use axum::Json;
use axum::Router;
use common::{init_tracing, splash, util::load_or_create_config};
use config::NapSdkConfig;
use serde_json::Value;
use sqlx::PgPool;
use tokio::net::TcpListener;

mod config;
mod database;
mod sdk_util;
mod services;

#[derive(Clone)]
pub struct SdkState {
    pub pg_pool: PgPool,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    splash::print("SDKServer");

    init_tracing(None);
    tracing::info!("don't forget to visit https://discord.xeondev.com/");

    let config = load_or_create_config::<NapSdkConfig>("nap_sdk.toml");

    let pg_pool = common::database::init(&config.database_credentials).await?;
    let state = SdkState { pg_pool };

    let router = Router::<SdkState>::new()
        .route("/sdk/dataUpload", post(data_upload))
        .merge(services::dispatch::routes())
        .merge(services::mdk_shield::routes())
        .merge(services::takumi_api::routes())
        .merge(services::granter_api::routes())
        .merge(services::registration_page::routes())
        .with_state(state)
        .fallback(fallback);

    let tcp_listener = TcpListener::bind(&config.http_addr).await?;
    tracing::info!("listening at {}", &config.http_addr);

    axum::serve(tcp_listener, router.into_make_service()).await?;
    Ok(())
}

async fn fallback(uri: Uri) -> impl IntoResponse {
    tracing::warn!("unhandled: {uri}");
    StatusCode::NOT_FOUND
}

pub async fn data_upload(_: Json<Value>) -> &'static str {
    r#"{"retcode": 0}"#
}
