<?php

namespace App\Helpers;

class ArrayHelper
{
    public static function multi_array_key_exists($key, array $array): bool
    {
        // If the key exists in the current array, return true
        if (array_key_exists($key, $array)) {
            return true;
        }

        // Check each element of the array recursively
        foreach ($array as $value) {
            if (is_array($value) && self::multi_array_key_exists($key, $value)) {
                return true;
            }
        }

        // If the key is not found in the array or its sub-arrays, return false
        return false;
    }

    public static function getKeysNotInSecondArray(array $firstArray, array $array2): array {
        $difference = array_diff_key($firstArray, $array2);

        return $difference;
    }

    public static function uniqueMulti(array $array, string $key): array
    {
        $temp_array = [];
        $key_array = [];
        foreach ($array as $val) {
            if (!in_array($val[$key], $key_array)) {
                $key_array[] = $val[$key];
                $temp_array[] = $val;
            }
        }
        return [$temp_array];
    }

    public static function uniqueSingle(array $array, string $key): array
    {
        $temp_array = [];
        $i = 0;
        $key_array = [];

        foreach ($array as $val) {
            if (!in_array($val[$key], $key_array)) {
                $key_array[$i] = $val[$key];
                $temp_array[$i] = $val;
            }
            $i++;
        }
        return $temp_array;
    }

    public static function getUniqueValues(array $data, $key) {
        // Extract unique values of "category"
        $categories = array_column($data, $key);
        $uniqueCategories = array_unique($categories);

        return $uniqueCategories;
        return [];
    }

    public static function convertRowsToColumn(array $arr, string $key, string $val): array
    {
        // Use array_column to get all the values of the specified key from the given array and filter them by the given value.
        return array_filter(array_column($arr, $key), function ($item) use ($val) {
            return $item == $val;
        });
    }

    public static function removeDuplicatesFromMultidimensionalArrayValues(array $array, string $key): array
    {
        $tempArray = [];
        $keyArray = [];

        foreach ($array as $val) {
            foreach ($val as $value1) {
                if (!in_array($value1[$key], $keyArray)) {
                    array_push($keyArray, $value1[$key]);
                    array_push($tempArray, $value1);
                }
            }
        }

        return [$tempArray];
    }

    public static function getKeyOffset(array $array, string|int $key): ?int
    {
        $keys = array_keys($array);
        $offset = array_search($key, $keys, true);
        return $offset !== false ? $offset : null;
    }

    public static function contains(array $array, mixed $value): bool
    {
        return in_array($value, $array);
    }

    public static function renameKey(array &$array, string|int $oldKey, string|int $newKey): bool
    {
        if (array_key_exists($oldKey, $array)) {
            $array[$newKey] = $array[$oldKey];
            unset($array[$oldKey]);
            return true;
        }
        return false;
    }

    public static function flatten(array $array, bool $preserveKeys = false): array
    {
        $result = [];
        array_walk_recursive($array, function ($a) use (&$result, $preserveKeys) {
            if ($preserveKeys) {
                $result[key($a)] = $a;
            } else {
                $result[] = $a;
            }
        });
        return $result;
    }

    public static function count(array $array): int
    {
        return count($array);
    }

    public static function multiArrayKeyExists($key, array $array): bool
    {
        foreach ($array as $item) {
            if (is_array($item)) {
                if (self::multiArrayKeyExists($key, $item)) {
                    return true;
                }
            } elseif ($item === $key) {
                return true;
            }
        }
        return false;
    }

    public static function compare(array $arr1, array $arr2): bool
    {
        return $arr1 == $arr2;
    }

    public static function getKeysByValue(array $array, $value): array
    {
        return array_keys($array, $value, true);
    }

    public static function containsKeys(array $keys, array $array): bool
    {
        return count(array_intersect_key(array_flip($keys), $array)) === count($keys);
    }

    public static function containsAny(array $items, array $array): bool
    {
        return count(array_intersect($items, $array)) > 0;
    }

    public static function removeByKey(array &$array, $key): void
    {
        unset($array[$key]);
    }

    public static function addByKey(array &$array, $key, $value): void
    {
        $array[$key] = $value;
    }

    public static function getValuesByKey(array $arrays, $key): array
    {
        return array_column($arrays, $key);
    }

    public static function getMatchingKeys(array $keys, array $arr): array
    {
        return array_intersect_key($arr, array_flip($keys));
    }

    public static function findKeyValue(array $array, string $key, string $val): ?array
    {
        foreach ($array as $item) {
            if (is_array($item) && array_key_exists($key, $item) && $item[$key] === $val) {
                return $item;
            }
        }
        return null;
    }

    public static function arrayDifferences(array $arr1, array $arr2): array
    {
        return array_diff_assoc($arr1, $arr2);
    }

    public static function getMissingKeys(array $array1, array $array2)
    {
        // Get keys that are present in the first array but not in the second
        $missing_in_array2 = array_diff_key($array1, $array2);

        // Get keys that are present in the second array but not in the first
        $missing_in_array1 = array_diff_key($array2, $array1);

        // Merge both sets of missing keys
        $missing_keys = array_merge($missing_in_array1, $missing_in_array2);

        return $missing_keys;
    }
}
