#!/usr/bin/env bash

# ============================================
# Core
# ============================================

LOG_LEVEL=${LOG_LEVEL:-INFO}

# ============================================
# Internal
# ============================================

function internal::get_log_priority() {
  case "$1" in
    DEBUG)   echo 0 ;;
    INFO)    echo 1 ;;
    SUCCESS) echo 1 ;;
    OK)      echo 1 ;;
    WARN)    echo 2 ;;
    ERROR)   echo 3 ;;
    *)       echo 1 ;;
  esac
}

function internal::log() {
  local level="$1"
  shift

  # Quiet mode — suppress INFO and SUCCESS
  if core::is_quiet; then
    case "$level" in
      INFO|SUCCESS) return 0 ;;
    esac
  fi

  local current_priority
  local message_priority
  current_priority=$(internal::get_log_priority "$LOG_LEVEL")
  message_priority=$(internal::get_log_priority "$level")

  if (( message_priority < current_priority )); then
    return 0
  fi

  local color
  case "$level" in
    DEBUG)   color="\033[0;36m"  ;;
    INFO)    color="\033[1;34m"  ;;
    WARN)    color="\033[1;33m"  ;;
    ERROR)   color="\033[1;31m"  ;;
    SUCCESS) color="\033[1;32m"  ;;
    OK)      color="\033[1;32m"  ;;
  esac

  echo -e "${color}=> ${level}:\033[0m $*"
}

function internal::icon() {
  local context="$1"
  local action="$2"

  case "$context:$action" in
    docker:log)       echo "🐳 "    ;;
    docker:start)     echo "🟢 🐳 " ;;
    docker:stop)      echo "🔴 🐳 " ;;
    docker:success)   echo "✅ 🐳 " ;;
    docker:warning)   echo "⚠️ 🐳 "  ;;
    docker:error)     echo "❌ 🐳 " ;;
    docker:logs)      echo "📜 🐳 " ;;
    docker:list)      echo "🔍 🐳 " ;;
    docker:build)     echo "📦 🐳 " ;;

    build:log)        echo "🏗️ "    ;;
    build:start)      echo "🟢 🏗️ " ;;
    build:stop)       echo "🔴 🏗️ " ;;
    build:success)    echo "✅ 🏗️ " ;;
    build:warning)    echo "⚠️ 🏗️ "  ;;
    build:error)      echo "❌ 🏗️ " ;;

    network:log)      echo "🌐 "    ;;
    network:setup)    echo "⚙️ 🌐 "  ;;
    network:stop)     echo "🔴 🌐 " ;;
    network:success)  echo "✅ 🌐 " ;;
    network:warning)  echo "⚠️ 🌐 "  ;;
    network:error)    echo "❌ 🌐 " ;;

    auth:log)         echo "🔑 "    ;;
    auth:setup)       echo "⚙️ 🔑 "  ;;
    auth:login)       echo "🔐 🔑 " ;;
    auth:success)     echo "✅ 🔑 " ;;
    auth:warning)     echo "⚠️ 🔑 "  ;;
    auth:error)       echo "❌ 🔑 " ;;

    env:log)          echo "⚙️ "    ;;
    env:load)         echo "📥 ⚙️ "  ;;
    env:success)      echo "✅ ⚙️ "  ;;
    env:warning)      echo "⚠️ ⚙️ "  ;;
    env:error)        echo "❌ ⚙️ "  ;;

    fs:log)           echo "📁 "    ;;
    fs:read)          echo "📥 📁 " ;;
    fs:write)         echo "📤 📁 " ;;
    fs:success)       echo "✅ 📁 " ;;
    fs:warning)       echo "⚠️ 📁 "  ;;
    fs:error)         echo "❌ 📁 " ;;

    db:log)           echo "🗄️ "    ;;
    db:start)         echo "🟢 🗄️ " ;;
    db:migrate)       echo "📜 🗄️ " ;;
    db:success)       echo "✅ 🗄️ "  ;;
    db:warning)       echo "⚠️ 🗄️ "  ;;
    db:error)         echo "❌ 🗄️ "  ;;

    wg:log)           echo "🔒 "    ;;
    wg:start)         echo "🟢 🔒 " ;;
    wg:stop)          echo "🔴 🔒 " ;;
    wg:add)           echo "➕ 🔒 " ;;
    wg:remove)        echo "➖ 🔒 " ;;
    wg:block)         echo "🚫 🔒 " ;;
    wg:unblock)       echo "🔓 🔒 " ;;
    wg:key)           echo "🔑 🔒 " ;;
    wg:success)       echo "✅ 🔒 " ;;
    wg:warning)       echo "⚠️ 🔒 "  ;;
    wg:error)         echo "❌ 🔒 " ;;
    wg:list)          echo "🔍 🔒 " ;;
    wg:qr)            echo "📱 🔒 " ;;
    wg:preset)        echo "📋 🔒 " ;;

    log:info)         echo "🔹 "    ;;
    log:warn)         echo "⚠️ "    ;;
    log:error)        echo "❌ "    ;;
    log:success)      echo "✅ "    ;;
    log:debug)        echo "🔍 "    ;;

    *) echo "🔹" ;;
  esac
}

function internal::get_context_icon() {
  case "$1" in
    docker)   echo "🐳"  ;;
    build)    echo "🏗️"  ;;
    network)  echo "🌐"  ;;
    auth)     echo "🔑"  ;;
    env)      echo "⚙️"  ;;
    fs)       echo "📁"  ;;
    db)       echo "🗄️"  ;;
    wg)       echo "🔒"  ;;
    log)      echo "🔹"  ;;
    *)        echo "🔹"  ;;
  esac
}

# ============================================
# Profiler
# ============================================

declare -gi _PROFILE_T0=0

function log::profile_start() {
  _PROFILE_T0=$(date +%s%3N)
}

function log::profile() {
  [[ "${LOG_LEVEL:-2}" -gt 0 ]] && return 0
  local label="${1:-checkpoint}"
  local now
  now=$(date +%s%3N)
  printf "  \033[2m[profile] %s: %dms\033[0m\n" \
    "$label" "$(( now - _PROFILE_T0 ))" >&2
  _PROFILE_T0=$now  # reset for next checkpoint
}

# ============================================
# Loggers
# ============================================

function internal::log::info()    { internal::log INFO    "$*"; }
function internal::log::warn()    { internal::log WARN    "$*"; }
function internal::log::error()   { internal::log ERROR   "$*"; }
function internal::log::success() { internal::log OK      "$*"; }
function internal::log::debug()   { internal::log DEBUG   "$*"; }

# ============================================
# Context Loggers
# ============================================

function log::context() {
  local context="$1" action="$2"
  shift 2
  internal::log::info "$(internal::icon "$context" "$action") $*"
}

function log::warn_context() {
  local context="$1" action="$2"
  shift 2
  internal::log::warn "$(internal::icon "$context" "$action") $*"
}

function log::error_context() {
  local context="$1" action="$2"
  shift 2
  internal::log::error "$(internal::icon "$context" "$action") $*"
}

function log::success_context() {
  local context="$1" action="$2"
  shift 2
  internal::log::success "$(internal::icon "$context" "$action") $*"
}

function log::debug_context() {
  local context="$1" action="$2"
  shift 2
  internal::log::debug "$(internal::icon "$context" "$action") $*"
}

# ============================================
# Logger Helpers
# ============================================

function log::info()    { log::context log info "$@"; }
function log::warn()    { log::warn_context log warn "$@"; }
function log::error()   { log::error_context log error "$@"; }
function log::ok()      { internal::log OK      "$@"; }
function log::success() { log::ok "$@"; }
function log::debug()   { log::debug_context log debug "$@"; }

function log::section() {
  core::is_quiet && return 0
  local label="$1"
  local width=48
  local line
  line=$(printf '─%.0s' $(seq 1 $width))
  echo -e "\n\033[1;34m${line}\033[0m"
  echo -e "\033[1;34m  $label\033[0m"
  echo -e "\033[1;34m${line}\033[0m"
}

# ============================================
# Docker
# ============================================

function log::docker()         { log::context docker log "$@"; }
function log::docker_start()   { log::context docker start "$@"; }
function log::docker_stop()    { log::context docker stop "$@"; }
function log::docker_success() { log::success_context docker success "$@"; }
function log::docker_logs()    { log::context docker logs "$@"; }
function log::docker_list()    { log::context docker list "$@"; }
function log::docker_build()   { log::context docker build "$@"; }
function log::docker_warning() { log::warn_context docker warning "$@"; }
function log::docker_error()   { log::error_context docker error "$@"; }

# ============================================
# Build
# ============================================

function log::build()          { log::context build log "$@"; }
function log::build_start()    { log::context build start "$@"; }
function log::build_stop()     { log::context build stop "$@"; }
function log::build_success()  { log::success_context build success "$@"; }
function log::build_warning()  { log::warn_context build warning "$@"; }
function log::build_error()    { log::error_context build error "$@"; }

# ============================================
# Network
# ============================================

function log::network()         { log::context network log "$@"; }
function log::network_setup()   { log::context network setup "$@"; }
function log::network_stop()    { log::context network stop "$@"; }
function log::network_success() { log::success_context network success "$@"; }
function log::network_warning() { log::warn_context network warning "$@"; }
function log::network_error()   { log::error_context network error "$@"; }

# ============================================
# Auth
# ============================================

function log::auth()          { log::context auth log "$@"; }
function log::auth_setup()    { log::context auth setup "$@"; }
function log::auth_login()    { log::context auth login "$@"; }
function log::auth_success()  { log::success_context auth success "$@"; }
function log::auth_warning()  { log::warn_context auth warning "$@"; }
function log::auth_error()    { log::error_context auth error "$@"; }

# ============================================
# Env
# ============================================

function log::env()          { log::context env log "$@"; }
function log::env_load()     { log::context env load "$@"; }
function log::env_success()  { log::success_context env success "$@"; }
function log::env_warning()  { log::warn_context env warning "$@"; }
function log::env_error()    { log::error_context env error "$@"; }

# ============================================
# Filesystem
# ============================================

function log::fs()          { log::context fs log "$@"; }
function log::fs_read()     { log::context fs read "$@"; }
function log::fs_write()    { log::context fs write "$@"; }
function log::fs_success()  { log::success_context fs success "$@"; }
function log::fs_warning()  { log::warn_context fs warning "$@"; }
function log::fs_error()    { log::error_context fs error "$@"; }

# ============================================
# Database
# ============================================

function log::db()          { log::context db log "$@"; }
function log::db_start()    { log::context db start "$@"; }
function log::db_migrate()  { log::context db migrate "$@"; }
function log::db_success()  { log::success_context db success "$@"; }
function log::db_warning()  { log::warn_context db warning "$@"; }
function log::db_error()    { log::error_context db error "$@"; }

# ============================================
# WireGuard
# ============================================

function log::wg()          { log::context wg log "$@"; }
function log::wg_start()    { log::context wg start "$@"; }
function log::wg_stop()     { log::context wg stop "$@"; }
function log::wg_add()      { log::context wg add "$@"; }
function log::wg_remove()   { log::context wg remove "$@"; }
function log::wg_key()      { log::context wg key "$@"; }
function log::wg_list()     { log::context wg list "$@"; }
function log::wg_qr()       { log::context wg qr "$@"; }
function log::wg_preset()   { log::context wg preset "$@"; }
function log::wg_success()  { log::success_context wg success "$@"; }
function log::wg_warning()  { log::warn_context wg warning "$@"; }
function log::wg_error()    { log::error_context wg error "$@"; }

function log::wg_block() {
  log::context wg block "$@"
}

function log::wg_unblock() {
  log::context wg unblock "$@"
}

# ============================================
# Run Step
# ============================================

function log::run_step() {
  local context="$1"
  local mode="strict"
  local description

  shift

  if [[ "$1" == "soft" || "$1" == "strict" || "$1" == "info" ]]; then
    mode="$1"
    shift
  fi

  description="$1"
  shift

  local icon
  icon=$(internal::get_context_icon "$context")

  if [[ "$mode" == "info" ]]; then
    internal::log::info "$icon  $description"
  else
    internal::log::info "🔄 $icon  $description"
  fi

  "$@"
  local status=$?

  if [[ $status -eq 0 ]]; then
    [[ "$mode" == "info" ]] && return 0
    internal::log::success "✅ $icon $description"
    return 0
  fi

  if [[ "$mode" == "soft" || "$mode" == "info" ]]; then
    internal::log::warn "⚠️ $icon $description → skipped"
    return 0
  fi

  internal::log::error "❌ $icon $description → failed"
  return $status
}