<?php

declare(strict_types=1);

namespace KimaAI\Admin;

defined('ABSPATH') || exit;

final class Utils {
  /**
   * Determines if a string ends with the given suffix.
   *
   * @param string $str The input string to check.
   * @param string $suffix The suffix to look for.
   * @return bool True if $str ends with $suffix, false otherwise.
   */
  public static function endsWith(string $str, string $suffix): bool {
    $len = strlen($suffix);
    return $len === 0 ? true : (substr($str, -$len) === $suffix);
  }

  /**
   * Returns the parent path of a dot-separated path string.
   *
   * For example, given 'foo.bar.baz', returns 'foo.bar'.
   *
   * @param string $path The dot-separated path string.
   * @return string The parent path, or an empty string if there is no parent.
   */
  public static function parentPath(string $path): string {
    $pos = strrpos($path, '.');
    return $pos === false ? '' : substr($path, 0, $pos);
  }

  /**
   * Retrieves a value from a nested array using a dot-separated path.
   *
   * @param array $arr The array to traverse.
   * @param string $path Dot-separated path (e.g., "foo.bar.baz") representing the keys to traverse.
   * @return mixed The value at the specified path, or NULL if the path does not exist.
   */
  public static function getByPath(array $arr, string $path) {
    if ($path === '') {
      return $arr;
    }
    $parts = explode('.', $path);
    $cur = $arr;
    foreach ($parts as $part) {
      if (!is_array($cur) || !array_key_exists($part, $cur)) {
        return null;
      }
      $cur = $cur[$part];
    }
    return $cur;
  }

  /**
   * Sets a value in a nested array using a dot-separated path.
   *
   * @param array $arr The array to modify.
   * @param string $path Dot-separated path (e.g., "foo.bar.baz") specifying the nested key.
   * @param mixed $value The value to set at the specified path.
   *
   * @return array The modified array with the value set at the given path.
   */
  public static function setByPath(array $arr, string $path, $value): array {
    $parts = explode('.', $path);
    $cur =& $arr;
    foreach ($parts as $i => $part) {
      if ($i === count($parts) - 1) {
        $cur[$part] = $value;
        return $arr;
      }
      if (!isset($cur[$part]) || !is_array($cur[$part])) {
        $cur[$part] = [];
      }
      $cur =& $cur[$part];
    }
    return $arr;
  }

  /**
   * Recursively flattens a multidimensional array.
   *
   * @param array $multidimensional_array The multidimensional array to flatten.
   * @return array The flattened array.
   */
  public static function flattenArray(array $multidimensional_array): array {
    $result = [];
    array_walk_recursive(
      $multidimensional_array,
      function ($value, $key) use (&$result) {
        $result[$key] = $value;
      }
    );
    return $result;
  }
}
