<?php

error_reporting(-1);

/* Возвращает соответствующую числу форму слова: 1 рубль, 2 тысячи, 5 миллионов */
function inclineWord($numbers, $isFemale, $key) {

    $spelling = [
        0 => [0 => 'рубль', 1 => 'рубля', 2 => 'рублей'],
        1 => [0 => 'тысяча', 1 => 'тысячи', 2 => 'тысяч'],
        2 => [0 => 'миллион', 1 => 'миллиона', 2 => 'миллионов'],
    ];

    if (arrayCheck($numbers)) {
        $numbers = array_reverse(combineNumbers(array_reverse($numbers)));
    }
    
    if ($numbers[0] == 1) {
        $word = $spelling[$key][0];
    } elseif ($numbers[0] >= 2 && $numbers[0] <= 4) {
        $word = $spelling[$key][1];
    } elseif ($numbers[0] >= 5 && $numbers[0] <= 9 || $numbers[0] >= 11 && $numbers[0] <= 19 || $numbers[0] == 0) {
        $word = $spelling[$key][2];
    }

    return $word;
}

/* Соединяет особенные числа */
function combineNumbers($numbers) {
    $keys = (count($numbers) == 4) ? [1, 2] : ((count($numbers) == 3) ? [0, 1] : null);

    if ($keys) {
        if (($numbers[$keys[0]] == 1) && ($numbers[$keys[1]] >= 1) && ($numbers[$keys[1]] <= 9)) {
            $numbers[$keys[0]] *= 10 + $numbers[$keys[1]];
            unset($numbers[$keys[1]]);
        }
    }

    return $numbers;
}
 
/* 
    Преобразует числа от 0 до 999 в текст. Параметр $isFemale равен нулю, 
    если мы считаем число для мужского рода (один рубль), 
    и 1 — для женского (одна тысяча) 
*/
function smallNumberToText($numbers, $isFemale ,$length) {
 
    $spelling = [
        0   =>  'ноль',                                     10  =>  'десять',        100 =>  'сто',
        1   =>  'один',         11  =>  'одиннадцать',      20  =>  'двадцать',      200 =>  'двести',
        2   =>  'два',          12  =>  'двенадцать',       30  =>  'тридцать',      300 =>  'триста',
        3   =>  'три',          13  =>  'тринадцать',       40  =>  'сорок',         400 =>  'четыреста',
        4   =>  'четыре',       14  =>  'четырнадцать',     50  =>  'пятьдесят',     500 =>  'пятьсот',
        5   =>  'пять',         15  =>  'пятнадцать',       60  =>  'шестьдесят',    600 =>  'шестьсот',
        6   =>  'шесть',        16  =>  'шестнадцать',      70  =>  'семьдесят',     700 =>  'семьсот',    
        7   =>  'семь',         17  =>  'семнадцать',       80  =>  'восемьдесят',   800 =>  'восемьсот',
        8   =>  'восемь',       18  =>  'восемнадцать',     90  =>  'девяносто',     900 =>  'девятьсот',
        9   =>  'девять',       19  =>  'девятнадцать'    
    ];

    if ($isFemale) {
        $femaleSpelling = [
            1 => 'одна',
            2 => 'две'
        ];

        $spelling = array_replace($spelling, $femaleSpelling);
    }
    
    if (arrayCheck($numbers)) {
        $numbers = combineNumbers(array_reverse($numbers));
    }
    unset($numbers['remainder']);

    $multiplierAndKey = (count($numbers) == 3) ? [100, 3] : ((count($numbers) == 2) ? (($length == 4) ? [100, 2] : [10, 2]) : [1, 1]);

    for ($i = 0; $i < $multiplierAndKey[1]; $i++) {
        if ($numbers[$i] != 0) {
            $words[] = $spelling[$numbers[$i] * $multiplierAndKey[0]];
        } else {
            $words[] = null;
        }
        $multiplierAndKey[0] = ($length == 4 && count($numbers) == 2) ? 1 : $multiplierAndKey[0] / 10;
    }

    return $words;
}

/* Разделяет число на массивы с числами */
function divideNumber($number, $minIteration, $maxIteration) {
    for ($i = $minIteration; $i < $maxIteration; $i++) {
        if ($number) {
            $numbers[] = $number % 10;
            $number = floor($number / 10);
            $numbers['remainder'] = $number;
        } elseif ($number == 0) {
            $numbers[] = null;
        }
    }
    
    return $numbers;
}

/* Проверяет массив на наличие реальных значений */
function arrayCheck($array) {
    $result = 0;
    foreach ($array as $variable) {
        if ($variable != null) {
            $result = 1;
        }
    }

    return $result;
}

function numberToText($number) {

    /*
    $key - номер ключа массива
    $min - мин. кол-во интераций
    $max - макс. кол-во итераций
    */

    for ($key = 0, $min = 0, $max = 3; $max <= 9; $key++, $min += 3, $max += 3) {

        if (!empty($numbers[$key - 1]['remainder']) || $key == 0) {

            if (!isset($numbers)) {
                $numbers[$key] = divideNumber($number, $min, $max);
            } else {
                $numbers[$key] = divideNumber($numbers[$key - 1]['remainder'], $min, $max);
            }

            $isFemale = 0;
            if ($numbers[$key][0] == 1 && $key == 1 || $numbers[$key][0] == 2 && $key == 1) {
                $isFemale = 1;
            }

            $inclinedWords[$key] = inclineWord($numbers[$key], $isFemale, $key);
            $words[$key] = smallNumberToText($numbers[$key], $isFemale, count($numbers[$key]));

            if ($key == 0) {
                if (arrayCheck($words[$key])) {
                    $text = implode(' ', $words[$key]);
                }
                if (isset($text)) {
                    $text = $text.' '."($number)".' '.$inclinedWords[$key];
                } else {
                    $text = "($number)".' '.$inclinedWords[$key];
                }
            } else {
                if (arrayCheck($words[$key])) {
                    $text = implode(' ', $words[$key]).' '.$inclinedWords[$key].' '.$text;
                }

            }

        }

    }

    return $text;
}

/* Вызовем функцию несколько раз */
for ($i = 0; $i < 5; $i++) {
    $amount[$i] = mt_rand(0, 999999999);
    $text[$i] = numberToText($amount[$i]);
    echo "На вашем счету: {$text[$i]}\n";
}