#!/usr/bin/env bash
# modules/resolve.module.sh — IP/host resolution chain
# Chains: hosts.json exact match → services.json match → raw IP
# Depends on: hosts.module.sh, net.module.sh

declare -gA _RESOLVE_CACHE=()

# resolve::ip <ip> [port] [proto]
# Resolves an IP to a display name using the full resolution chain.
# Returns raw IP if no match found.
# Respects _WGCTL_RAW=true to bypass resolution.
function resolve::ip() {
  local ip="${1:-}" port="${2:-}" proto="${3:-}"
  [[ -z "$ip" ]] && echo "" && return 0
  [[ "${_WGCTL_RAW:-false}" == "true" ]] && echo "$ip" && return 0

  local cache_key="${ip}:${port}:${proto}"
  if [[ -z "${_RESOLVE_CACHE[$cache_key]+x}" ]]; then
    local result=""

    # 1. hosts.json exact IP match
    if [[ -f "$(ctx::hosts)" ]]; then
      result=$(hosts::resolve_ip "$ip")
    fi

    # 2. services.json match
    if [[ -z "$result" ]]; then
      result=$(net::reverse_lookup "$ip" "$port" "$proto" 2>/dev/null) || result=""
    fi

    # 3. Raw IP fallback
    [[ -z "$result" ]] && result="$ip"

    _RESOLVE_CACHE[$cache_key]="$result"
  fi

  echo "${_RESOLVE_CACHE[$cache_key]}"
}

# resolve::dest <ip> [port] [proto]
# Like resolve::ip but builds a formatted destination display string.
# e.g. "pihole:dns-udp" or "vodafone-wan" or "10.0.0.103:853/tcp"
function resolve::dest() {
  local ip="${1:-}" port="${2:-}" proto="${3:-}"
  [[ -z "$ip" ]] && echo "" && return 0

  local name
  name=$(resolve::ip "$ip" "$port" "$proto")

  if [[ "$name" == "$ip" ]]; then
    # No resolution — raw format
    if [[ -n "$port" ]]; then
      echo "${ip}:${port}/${proto}"
    else
      [[ -n "$proto" ]] && echo "${ip} (${proto})" || echo "$ip"
    fi
  else
    # Resolved — just the name, no proto suffix
    echo "$name"
  fi
}

# resolve::clear_cache
# Clears the resolution cache — call between commands if needed.
function resolve::clear_cache() {
  _RESOLVE_CACHE=()
}