#!/usr/bin/env bash

MODULE_NETWORK_IP_CONFIG_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULE_NETWORK_IP_CONFIG_PROJECT_ROOT="$(cd "$MODULE_NETWORK_IP_CONFIG_DIR/../../.." && pwd)"

# shellcheck source=lib/system.sh
source "$MODULE_NETWORK_IP_CONFIG_PROJECT_ROOT/lib/system.sh"
# shellcheck source=modules/network/ip-config/config.sh
source "$MODULE_NETWORK_IP_CONFIG_DIR/config.sh"
# shellcheck source=modules/network/ip-config/metadata.conf
source "$MODULE_NETWORK_IP_CONFIG_DIR/metadata.conf"

module_ip_config_metadata() {
  printf '%s|%s|%s\n' "$MODULE_ID" "$MODULE_NAME" "$MODULE_DESCRIPTION"
}

module_ip_config_detect_backend() {
  if command -v nmcli >/dev/null 2>&1 && systemctl is-active --quiet NetworkManager; then
    printf 'networkmanager\n'
  elif [[ -d /etc/systemd/network ]]; then
    printf 'networkd\n'
  else
    printf 'ifupdown\n'
  fi
}

module_ip_config_validate_mode() {
  [[ "$1" == "dhcp" || "$1" == "static" ]]
}

module_ip_config_nmcli_connection_for_device() {
  local iface="$1"
  nmcli -t -f NAME,DEVICE connection show | awk -F: -v iface="$iface" '$2 == iface { print $1; exit }'
}

module_ip_config_write_networkd() {
  local iface="$1"
  local mode="$2"
  local address="$3"
  local prefix="$4"
  local gateway="$5"
  local dns="$6"
  local file_path="/etc/systemd/network/10-postinstall-${iface}.network"

  mkdir -p /etc/systemd/network
  {
    printf '[Match]\nName=%s\n\n' "$iface"
    printf '[Network]\n'
    if [[ "$mode" == "dhcp" ]]; then
      printf 'DHCP=yes\n'
    else
      printf 'Address=%s/%s\n' "$address" "$prefix"
      printf 'Gateway=%s\n' "$gateway"
      printf 'DNS=%s\n' "$dns"
    fi
  } > "$file_path"

  if systemctl is-active --quiet systemd-networkd; then
    systemctl restart systemd-networkd
  fi
}

module_ip_config_write_ifupdown() {
  local iface="$1"
  local mode="$2"
  local address="$3"
  local prefix="$4"
  local gateway="$5"
  local dns="$6"
  local netmask="255.255.252.0"
  local file_path="/etc/network/interfaces.d/postinstall-${iface}"

  mkdir -p /etc/network/interfaces.d
  {
    printf 'auto %s\n' "$iface"
    if [[ "$mode" == "dhcp" ]]; then
      printf 'iface %s inet dhcp\n' "$iface"
    else
      printf 'iface %s inet static\n' "$iface"
      printf '    address %s/%s\n' "$address" "$prefix"
      printf '    gateway %s\n' "$gateway"
      printf '    dns-nameservers %s\n' "$dns"
      printf '    netmask %s\n' "$netmask"
    fi
  } > "$file_path"
}

module_ip_config_write_networkmanager() {
  local iface="$1"
  local mode="$2"
  local address="$3"
  local prefix="$4"
  local gateway="$5"
  local dns="$6"
  local connection_name=""

  connection_name="$(module_ip_config_nmcli_connection_for_device "$iface")"
  if [[ -z "$connection_name" ]]; then
    connection_name="postinstall-${iface}"
    nmcli connection add type ethernet ifname "$iface" con-name "$connection_name" >/dev/null
  fi

  if [[ "$mode" == "dhcp" ]]; then
    nmcli connection modify "$connection_name" ipv4.method auto ipv4.addresses "" ipv4.gateway "" ipv4.dns ""
  else
    nmcli connection modify "$connection_name" ipv4.method manual ipv4.addresses "$address/$prefix" ipv4.gateway "$gateway" ipv4.dns "$dns"
  fi
  nmcli connection up "$connection_name" >/dev/null
}

module_ip_config_install() {
  local iface="${1:-$POSTINSTALL_NETWORK_IP_DEFAULT_INTERFACE}"
  local mode="${2:-$POSTINSTALL_NETWORK_IP_DEFAULT_MODE}"
  local address="${3:-$POSTINSTALL_NETWORK_IP_DEFAULT_ADDRESS}"
  local prefix="${4:-$POSTINSTALL_NETWORK_IP_DEFAULT_PREFIX}"
  local gateway="${5:-$POSTINSTALL_NETWORK_IP_DEFAULT_GATEWAY}"
  local dns="${6:-$POSTINSTALL_NETWORK_IP_DEFAULT_DNS}"
  local backend=""

  iface="${iface:-$(system_primary_interface)}"

  if [[ -z "$iface" ]]; then
    ui_error "Impossible de detecter l'interface reseau"
    return 1
  fi

  if ! module_ip_config_validate_mode "$mode"; then
    ui_error "Mode reseau invalide : $mode"
    return 1
  fi

  backend="$(module_ip_config_detect_backend)"
  case "$backend" in
    networkmanager) module_ip_config_write_networkmanager "$iface" "$mode" "$address" "$prefix" "$gateway" "$dns" ;;
    networkd) module_ip_config_write_networkd "$iface" "$mode" "$address" "$prefix" "$gateway" "$dns" ;;
    *) module_ip_config_write_ifupdown "$iface" "$mode" "$address" "$prefix" "$gateway" "$dns" ;;
  esac

  mkdir -p "$(dirname "$POSTINSTALL_NETWORK_IP_STATE_FILE")"
  {
    printf 'INTERFACE=%s\n' "$iface"
    printf 'MODE=%s\n' "$mode"
    printf 'BACKEND=%s\n' "$backend"
    printf 'ADDRESS=%s\n' "$address"
    printf 'PREFIX=%s\n' "$prefix"
    printf 'GATEWAY=%s\n' "$gateway"
    printf 'DNS=%s\n' "$dns"
  } > "$POSTINSTALL_NETWORK_IP_STATE_FILE"

  log_info "Configuration IP appliquee sur $iface via $backend"
  ui_success "Configuration IP appliquee sur $iface via $backend"
}

module_ip_config_test() {
  test -f "$POSTINSTALL_NETWORK_IP_STATE_FILE" || return 1
  ip addr >/dev/null 2>&1 || return 1
}
