use std::net::SocketAddr;

use tonic::transport::Server;
use tonic::{Request, Response, Status};

use crate::protocol::game_service_server::{GameService, GameServiceServer};
use crate::protocol::general_service_server::{GeneralService, GeneralServiceServer};
use crate::protocol::{
    Empty, LoginRequest, LoginResponse, RequestResult, ServerInfo, SignupRequest, SignupResponse,
};

pub(crate) struct GrpcServer;

impl GrpcServer {
    pub(crate) async fn init() {
        let addr = SocketAddr::new([127, 0, 0, 1].into(), 12345);

        let general_service = GeneralServiceServer::new(GeneralServiceImpl);
        let game_service = GameServiceServer::new(GameServiceImpl);

        Server::builder()
            .add_service(general_service)
            .add_service(game_service)
            .serve(addr)
            .await
            .unwrap_or_else(|e| log::error!("Failed to build server: {e}"));
    }
}

// Define server implementations

struct GeneralServiceImpl;
struct GameServiceImpl;

#[tonic::async_trait]
impl GeneralService for GeneralServiceImpl {
    async fn get_server_info(
        &self,
        _request: Request<Empty>,
    ) -> Result<Response<ServerInfo>, Status> {
        Ok(Response::new(ServerInfo {
            lang: "Rust".into(),
            ver: "0.1.0".into(),
        }))
    }
}

#[tonic::async_trait]
impl GameService for GameServiceImpl {
    async fn login(
        &self,
        request: Request<LoginRequest>,
    ) -> Result<Response<LoginResponse>, Status> {
        log::info!("User {} logged in!", request.get_ref().username);

        Ok(Response::new(LoginResponse {
            result: RequestResult::Success.into(),
            message: "".into(),
        }))
    }

    async fn signup(
        &self,
        request: Request<SignupRequest>,
    ) -> Result<Response<SignupResponse>, Status> {
        log::info!("User {} signed up!", request.get_ref().username);

        Ok(Response::new(SignupResponse {
            result: RequestResult::Success.into(),
            message: "".into(),
        }))
    }
}
