//! Shared helpers for remote peer identity and legacy game announcements.

use std::{collections::HashMap, net::SocketAddr, sync::Arc};

use lanspread_db::db::Game;
use lanspread_proto::GameSummary;
use tokio::sync::RwLock;

use crate::{
    library::compute_library_digest,
    peer_db::{PeerGameDB, PeerId},
};

pub async fn ensure_peer_id_for_addr(
    peer_game_db: &Arc<RwLock<PeerGameDB>>,
    peer_addr: SocketAddr,
) -> PeerId {
    let mut db = peer_game_db.write().await;
    if let Some(peer_id) = db.peer_id_for_addr(&peer_addr).cloned() {
        return peer_id;
    }

    let legacy_id = format!("legacy-{peer_addr}");
    db.upsert_peer(legacy_id.clone(), peer_addr);
    legacy_id
}

pub fn summary_from_game(game: &Game) -> GameSummary {
    GameSummary {
        id: game.id.clone(),
        name: game.name.clone(),
        size: game.size,
        downloaded: game.downloaded,
        installed: game.installed,
        eti_version: game.eti_game_version.clone(),
        manifest_hash: 0,
        availability: game.normalized_availability(),
    }
}

pub async fn update_peer_from_game_list(
    peer_game_db: &Arc<RwLock<PeerGameDB>>,
    peer_addr: SocketAddr,
    games: &[Game],
) -> Vec<Game> {
    let summaries = games.iter().map(summary_from_game).collect::<Vec<_>>();
    let mut by_id = HashMap::with_capacity(summaries.len());
    for summary in &summaries {
        by_id.insert(summary.id.clone(), summary.clone());
    }
    let digest = compute_library_digest(&by_id);
    let peer_id = ensure_peer_id_for_addr(peer_game_db, peer_addr).await;

    let mut db = peer_game_db.write().await;
    db.update_peer_games(&peer_id, summaries);
    let features = db.peer_features(&peer_id);
    db.update_peer_library(&peer_id, 0, digest, features);
    db.get_all_games()
}
