#!/usr/bin/env bash
# commands/import.command.sh

function cmd::import::on_load() {
  flag::register --file
  flag::register --peer
  flag::register --dry-run
  flag::register --force
}

function cmd::import::help() {
  cat <<EOF
Usage: wgctl import --file <file> [options]

Import a wgctl JSON export bundle.

Options:
  --file <path>   Path to export bundle (required)
  --peer <name>   Import only this peer from a full backup
  --dry-run       Show what would be imported without making changes
  --force         Overwrite existing data

Export types handled:
  peer        Single peer bundle
  peer_conf   Peer conf only
  peer_meta   Peer meta only
  identity    Identity bundle
  full        Full backup

Examples:
  wgctl import --file backup.json
  wgctl import --file backup.json --peer phone-nuno
  wgctl import --file phone-nuno.json --dry-run
  wgctl import --file backup.json --force
EOF
}

function cmd::import::run() {
  local file="" peer="" dry_run=false force=false

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --file)    file="$2";        shift 2 ;;
      --peer)    peer="$2";        shift 2 ;;
      --dry-run) dry_run=true;     shift   ;;
      --force)   force=true;       shift   ;;
      --help)    cmd::import::help; return ;;
      *) log::error "Unknown flag: $1"; return 1 ;;
    esac
  done

  [[ -z "$file" ]] && log::error "Missing required flag: --file" && return 1
  [[ ! -f "$file" ]] && log::error "File not found: ${file}" && return 1

  # Read export metadata via Python
  local export_type export_version
  export_type=$(json::import_get_field \
    "$file" "export_type" 2>/dev/null)
  export_version=$(json::import_get_field \
    "$file" "wgctl_version" 2>/dev/null)

  [[ -z "$export_type" ]] && \
    log::error "Invalid export file: ${file}" && return 1

  # Version check
  local current_version
  current_version=$(wgctl::version 2>/dev/null || echo "unknown")
  if [[ "$export_version" != "$current_version" ]]; then
    log::wg_warning "Export version (${export_version}) differs from current (${current_version})"
  fi

  log::section "wgctl Import"
  printf "  File:    %s\n" "$file"
  printf "  Type:    %s\n" "$export_type"
  $dry_run && printf "  Mode:    \033[2mdry run\033[0m\n"
  printf "\n"

  case "$export_type" in
    peer)      cmd::import::_peer      "$file" "$dry_run" "$force" ;;
    peer_conf) cmd::import::_peer_conf "$file" "$dry_run" "$force" ;;
    peer_meta) cmd::import::_peer_meta "$file" "$dry_run" "$force" ;;
    identity)  cmd::import::_identity  "$file" "$dry_run" "$force" ;;
    full)
      if [[ -n "$peer" ]]; then
        cmd::import::_peer_from_full "$file" "$peer" "$dry_run" "$force"
      else
        cmd::import::_full "$file" "$dry_run" "$force"
      fi
      ;;
    *)
      log::error "Unknown export type: ${export_type}"
      return 1
      ;;
  esac
}

# ======================================================
# Helpers
# ======================================================

function cmd::import::_print_results() {
  while IFS= read -r line; do
    [[ -z "$line" ]] && continue
    case "$line" in
      error:*)  log::error "${line#error:}" ;;
      skip:*)   printf "  \033[2mskip: %s (already exists)\033[0m\n" "${line#skip:}" ;;
      peer:*)   printf "  ✓ peer: %s\n" "${line#peer:}" ;;
      group:*)  printf "  ✓ group: %s\n" "${line#group:}" ;;
      *)        printf "  ✓ %s\n" "$line" ;;
    esac
  done
}

# ======================================================
# Peer import
# ======================================================

function cmd::import::_peer() {
  local file="${1:-}" dry_run="${2:-false}" force="${3:-false}"

  local name
  name=$(json::import_get_field "$file" "data" "name" 2>/dev/null)
  [[ -z "$name" ]] && log::error "Could not read peer name from export" && return 1

  $dry_run && \
    printf "  \033[2m[dry-run]\033[0m Would import peer '%s'\n" "$name" && return 0

  local err
  err=$(json::import_peer \
    "$file" "data" "$name" \
    "$(ctx::clients)" "$(ctx::meta)" \
    "$(ctx::groups)" "$(ctx::blocks)" \
    "$($force && echo true || echo false)" \
    2>&1 >/dev/null) || { log::error "$err"; return 1; }

  json::import_peer \
    "$file" "data" "$name" \
    "$(ctx::clients)" "$(ctx::meta)" \
    "$(ctx::groups)" "$(ctx::blocks)" \
    "$($force && echo true || echo false)" \
    2>/dev/null | cmd::import::_print_results

  log::wg_success "Imported peer '${name}'"
}

# ======================================================
# Peer conf only
# ======================================================

function cmd::import::_peer_conf() {
  local file="${1:-}" dry_run="${2:-false}" force="${3:-false}"

  local name
  name=$(json::import_get_field "$file" "data" "name" 2>/dev/null)
  local conf_file="$(ctx::clients)/${name}.conf"

  if [[ -f "$conf_file" ]] && ! $force; then
    log::error "Peer conf '${name}' already exists. Use --force to overwrite."
    return 1
  fi

  $dry_run && \
    printf "  \033[2m[dry-run]\033[0m Would import conf for '%s'\n" "$name" && return 0

  python3 -c "
import json, base64
d = json.load(open('${file}'))
conf = base64.b64decode(d['data']['conf']).decode()
open('${conf_file}', 'w').write(conf)
" 2>/dev/null || { log::error "Failed to write conf"; return 1; }

  printf "  ✓ conf\n"
  log::wg_success "Imported conf for '${name}'"
}

# ======================================================
# Peer meta only
# ======================================================

function cmd::import::_peer_meta() {
  local file="${1:-}" dry_run="${2:-false}" force="${3:-false}"

  local name
  name=$(json::import_get_field "$file" "data" "name" 2>/dev/null)

  [[ ! -f "$(ctx::clients)/${name}.conf" ]] && \
    log::error "Peer '${name}' does not exist — import the peer conf first" && return 1

  $dry_run && \
    printf "  \033[2m[dry-run]\033[0m Would import meta for '%s'\n" "$name" && return 0

  python3 -c "
import json
d = json.load(open('${file}'))
meta = d['data']['meta']
open('$(ctx::meta)/${name}.meta', 'w').write(json.dumps(meta, indent=2))
" 2>/dev/null || { log::error "Failed to write meta"; return 1; }

  printf "  ✓ meta\n"
  log::wg_success "Imported meta for '${name}'"
}

# ======================================================
# Identity import
# ======================================================

function cmd::import::_identity() {
  local file="${1:-}" dry_run="${2:-false}" force="${3:-false}"

  local name
  name=$(json::import_get_field "$file" "data" "name" 2>/dev/null)

  $dry_run && \
    printf "  \033[2m[dry-run]\033[0m Would import identity '%s'\n" "$name" && return 0

  local err
  err=$(json::import_identity \
    "$file" "$name" \
    "$(ctx::identities)" "$(ctx::clients)" \
    "$($force && echo true || echo false)" \
    2>&1 >/dev/null) || { log::error "$err"; return 1; }

  json::import_identity \
    "$file" "$name" \
    "$(ctx::identities)" "$(ctx::clients)" \
    "$($force && echo true || echo false)" \
    2>/dev/null | cmd::import::_print_results

  log::wg_success "Imported identity '${name}'"
}

# ======================================================
# Single peer from full backup
# ======================================================

function cmd::import::_peer_from_full() {
  local file="${1:-}" name="${2:-}" dry_run="${3:-false}" force="${4:-false}"

  $dry_run && \
    printf "  \033[2m[dry-run]\033[0m Would import peer '%s' from backup\n" "$name" && return 0

  local err
  err=$(json::import_peer \
    "$file" "peers" "$name" \
    "$(ctx::clients)" "$(ctx::meta)" \
    "$(ctx::groups)" "$(ctx::blocks)" \
    "$($force && echo true || echo false)" \
    2>&1 >/dev/null) || { log::error "$err"; return 1; }

  json::import_peer \
    "$file" "peers" "$name" \
    "$(ctx::clients)" "$(ctx::meta)" \
    "$(ctx::groups)" "$(ctx::blocks)" \
    "$($force && echo true || echo false)" \
    2>/dev/null | cmd::import::_print_results

  log::wg_success "Imported peer '${name}' from backup"
}

# ======================================================
# Full backup import
# ======================================================

function cmd::import::_full() {
  local file="${1:-}" dry_run="${2:-false}" force="${3:-false}"

  local peer_count
  peer_count=$(json::import_get_field \
    "$file" "data" "peers" 2>/dev/null | python3 -c \
    "import json,sys; print(len(json.load(sys.stdin)))" 2>/dev/null || echo "?")

  printf "  Importing full backup (%s peers)...\n\n" "$peer_count"

  $dry_run && \
    log::wg_warning "Dry run — no changes would be made" && return 0

  json::import_full \
    "$file" \
    "$(ctx::clients)" "$(ctx::meta)" \
    "$(ctx::rules)" "$(ctx::identities)" \
    "$(ctx::groups)" "$(ctx::blocks)" \
    "$(ctx::policies)" "$(ctx::subnets)" \
    "$(ctx::net)" "$(ctx::hosts)" \
    "$($force && echo true || echo false)" \
    2>/dev/null | cmd::import::_print_results

  log::wg_success "Import complete"
}