mod auth;
mod config;
mod database;
mod dto;
mod handlers;
mod middleware;
mod models;
mod repositories;
mod routes;
mod services;

use std::net::SocketAddr;

use axum::Router;
use sqlx::PgPool;
use tower_http::trace::TraceLayer;

use crate::config::AppConfig;
use crate::routes::create_router;

#[derive(Clone)]
pub struct AppState {
    pub pool: PgPool,
    pub config: AppConfig,
}

#[tokio::main]
async fn main() {
    dotenvy::dotenv().ok();

    tracing_subscriber::fmt::init();

    let config = AppConfig::from_env();

    let pool = database::init_db_pool(&config.database_url).await;

    tracing::info!("Database connection established");

    let state = AppState {
        pool,
        config: config.clone(),
    };

    let app: Router = create_router(state)
        .layer(TraceLayer::new_for_http())
        .layer(middleware::cors_layer());

    let addr: SocketAddr = format!("{}:{}", config.host, config.port)
        .parse()
        .expect("Invalid host or port");

    tracing::info!("CRM API server starting on {}", addr);

    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
    axum::serve(listener, app).await.unwrap();
}
