#!/usr/bin/env bash

# ============================================
# Lifecycle
# ============================================

function config::on_load() {
  config::validate
}

# ============================================
# Server
# ============================================

WG_INTERFACE="wg0"
WG_CONFIG="$(ctx::wg)/${WG_INTERFACE}.conf"
WG_SERVER_PUBLIC_KEY_FILE="$(ctx::wg)/server_public.key"
WG_SERVER_PRIVATE_KEY_FILE="$(ctx::wg)/server_private.key"
WG_ENDPOINT="wg.krilio.net:51820"
WG_DNS="10.0.0.103"
WG_LISTEN_PORT="51820"
WG_SUBNET="10.1.0.0/16"
WG_LAN="10.0.0.0/24"

# ============================================
# Device Type → Subnet Mapping
# ============================================

declare -gA DEVICE_SUBNETS=(
  [desktop]="10.1.1"
  [laptop]="10.1.2"
  [phone]="10.1.3"
  [tablet]="10.1.4"
  [guest]="10.1.100"
)

# ============================================
# Tunnel Modes
# ============================================

# split — route only VPN subnet + LAN through WireGuard
# full  — route all traffic through WireGuard
WG_TUNNEL_SPLIT="${WG_SUBNET}, ${WG_LAN}"
WG_TUNNEL_FULL="0.0.0.0/0, ::/0"

# Default tunnel mode per device type
declare -gA DEVICE_TUNNEL_MODE=(
  [desktop]="split"
  [laptop]="split"
  [phone]="split"
  [tablet]="split"
  [guest]="split"
)

# ============================================
# Accessors
# ============================================

function config::interface()    { echo "$WG_INTERFACE"; }
function config::config_file()  { echo "$WG_CONFIG"; }
function config::endpoint()     { echo "$WG_ENDPOINT"; }
function config::dns()          { echo "$WG_DNS"; }
function config::listen_port()  { echo "$WG_LISTEN_PORT"; }
function config::subnet()       { echo "$WG_SUBNET"; }
function config::lan()          { echo "$WG_LAN"; }
function config::tunnel_split() { echo "$WG_TUNNEL_SPLIT"; }
function config::tunnel_full()  { echo "$WG_TUNNEL_FULL"; }

function config::server_public_key() {
  cat "$WG_SERVER_PUBLIC_KEY_FILE"
}

function config::device_types() {
  local types
  { set +u; types="${!DEVICE_SUBNETS[@]}"; set -u; }
  echo "$types"
}

function config::is_valid_type() {
  local type="$1"
  local subnet
  subnet=$(config::subnet_for "$type")
  [[ -n "$subnet" ]]
}

function config::subnet_for() {
  local type="$1"
  local result
  { set +u; result="${DEVICE_SUBNETS[$type]:-}"; set -u; }
  echo "$result"
}

function config::default_tunnel_for() {
  local type="$1"
  local result
  { set +u; result="${DEVICE_TUNNEL_MODE[$type]:-split}"; set -u; }
  echo "$result"
}

function config::allowed_ips_for() {
  local type="$1"
  local tunnel="${2:-}"

  # If tunnel mode not specified, use device default
  if [[ -z "$tunnel" ]]; then
    tunnel=$(config::default_tunnel_for "$type")
  fi

  case "$tunnel" in
    full)  echo "$WG_TUNNEL_FULL" ;;
    split) echo "$WG_TUNNEL_SPLIT" ;;
    *)
      log::error "Unknown tunnel mode: ${tunnel} (use 'split' or 'full')"
      return 1
      ;;
  esac
}

# ============================================
# Validation
# ============================================

function config::validate() {
  if [[ ! -f "$WG_SERVER_PUBLIC_KEY_FILE" ]]; then
    log::error "Server public key not found: ${WG_SERVER_PUBLIC_KEY_FILE}"
    exit 1
  fi

  if [[ ! -f "$WG_SERVER_PRIVATE_KEY_FILE" ]]; then
    log::error "Server private key not found: ${WG_SERVER_PRIVATE_KEY_FILE}"
    exit 1
  fi

  if [[ ! -f "$WG_CONFIG" ]]; then
    log::error "WireGuard config not found: ${WG_CONFIG}"
    exit 1
  fi
}