use axum::serve;
use axum::Extension;
use axum::extract::{ws::{Message, WebSocket, WebSocketUpgrade}, State};
use jsonwebtoken::{DecodingKey, EncodingKey};
use reqwest::header::AUTHORIZATION;
use reqwest::header::CONTENT_TYPE;
use tokio::net::TcpListener;
use tokio::sync::mpsc;

use reqwest::Client;

mod utils;
mod routes;
mod rooms;
mod chat;
mod inventory;
use r2d2::{Pool};
use r2d2_sqlite::SqliteConnectionManager;
use dashmap::DashMap;
use std::sync::Arc;

use crate::utils::db_pool::{HotelPool,AppState};
use routes::create_router;
use crate::utils::auth::JwtKeys;

use std::env;
use dotenvy::dotenv;

use tower_http::cors::{CorsLayer, Any};
use axum::http::{Method, HeaderValue};

pub async fn notify_discord(msg: &str) -> Result<(), reqwest::Error> {
    let payload = serde_json::json!({
        "content": msg
    });

    reqwest::Client::new()
        .post("https://discord.com/api/webhooks/1440912618205347891/Ekg89krDoPm41kA27LA3gXgNWmMWvCCtziYIUsjqaY22Jnw4a6IWhZOht0in5JjnPX-W")
        .json(&payload)
        .send()
        .await?;

    Ok(())
}


#[tokio::main(flavor = "multi_thread", worker_threads = 8)]
async fn main() -> std::io::Result<()> {

    dotenv().ok();

std::panic::set_hook(Box::new(|info| {
    let msg = format!("Rust panic: {}", info);

    // Use blocking client so the process can't exit before sending
    let payload = serde_json::json!({
        "content": msg
    });

    let client = reqwest::blocking::Client::new();
    let _ = client
        .post("https://discord.com/api/webhooks/1440912618205347891/Ekg89krDoPm41kA27LA3gXgNWmMWvCCtziYIUsjqaY22Jnw4a6IWhZOht0in5JjnPX-W")
        .json(&payload)
        .send();
}));

//panic!("crash-test");

    let hotel_pools = HotelPool::new();
    let logs_manager = SqliteConnectionManager::file("db/auth_copy_2.sqlite");
    let logs_pool = Pool::builder()
        .max_size(5)
        .build(logs_manager)
        .expect("Failed to build logs pool");

    let state = AppState {
        hotel_pools,
        logs_pool,
        ws_map: Arc::new(DashMap::new()), 
        //jwt_secret: "your_jwt_secret_key s".to_string(), // better: load from env var
    };

    //let jwt_secret = "your_jwt_secret_key".to_string();
    
    let jwt_secret = env::var("JWT_SECRET")
        .expect("JWT_SECRET must be set")
        .to_string();
    
    let jwt_keys = JwtKeys {
        encoding: EncodingKey::from_secret(jwt_secret.as_ref()),
        decoding: DecodingKey::from_secret(jwt_secret.as_ref()),
    };


    let cors = CorsLayer::new()
        .allow_origin("http://localhost:5173".parse::<HeaderValue>().unwrap())
        .allow_credentials(true)
        .allow_methods([Method::GET, Method::POST, Method::PUT , Method::OPTIONS])
        .allow_headers([CONTENT_TYPE, AUTHORIZATION]);

    let app = create_router(state)
        .layer(Extension(jwt_keys))
        .layer(cors);

    let listener = TcpListener::bind("0.0.0.0:7080").await?;
    serve(listener, app).into_future().await?;
    Ok(())
}

async fn handler() -> &'static str {
    "Hiii from localhost"
}