import gleam/bit_array
import gleam/crypto
import gleam/dynamic/decode
import gleam/json
import gleam/option.{type Option}

pub type PlayerSession {
  PlayerSession(
    id: Int,
    token_hash: String,
    username: String,
    socket_id: Option(Int),
  )
}

pub fn encode_player_session(player_session: PlayerSession) -> json.Json {
  json.object([
    #("id", json.int(player_session.id)),
    #("token_hash", json.string(player_session.token_hash)),
    #("username", json.string(player_session.username)),
    #("socket_id", case player_session.socket_id {
      option.None -> json.null()
      option.Some(value) -> json.int(value)
    }),
  ])
}

pub fn player_session_decoder() -> decode.Decoder(PlayerSession) {
  use id <- decode.field("id", decode.int)
  use token_hash <- decode.field("token_hash", decode.string)
  use username <- decode.field("username", decode.string)
  use socket_id <- decode.field("socket_id", decode.optional(decode.int))
  decode.success(PlayerSession(id:, token_hash:, username:, socket_id:))
}

pub fn hash_token(token: String) -> String {
  crypto.new_hasher(crypto.Sha512)
  |> crypto.hash_chunk(bit_array.from_string(token))
  |> crypto.digest
  |> bit_array.base64_encode(True)
}
