<?php
/**
 * (c) ININOUT & PYXIS. All Rights Reserved.
 * Wszelkie modyfikacje tego pliku wymagaja zgloszenia oraz zgody autorow.
 * Any modifications to this file require notification and consent of the authors.
 */
/**
 * i-BOK 5 - Funkcje pomocnicze
 */

/**
 * Kwota słownie (polski) - konwersja kwoty na zapis słowny
 */
function d2w($digits) {
    $jednosci = ['zero','jeden','dwa','trzy','cztery','pięć','sześć','siedem','osiem','dziewięć'];
    $dziesiatki = ['','dziesięć','dwadzieścia','trzydzieści','czterdzieści','pięćdziesiąt','sześćdziesiąt','siedemdziesiąt','osiemdziesiąt','dziewięćdziesiąt'];
    $setki = ['','sto','dwieście','trzysta','czterysta','pięćset','sześćset','siedemset','osiemset','dziewięćset'];
    $nastki = ['dziesięć','jedenaście','dwanaście','trzynaście','czternaście','piętnaście','szesnaście','siedemnaście','osiemnaście','dziewiętnaście'];
    $tysiace = ['tysiąc','tysiące','tysięcy'];

    $digits = (string)$digits;
    $digits = strrev($digits);
    $i = strlen($digits);
    $string = '';

    if ($i > 5 && isset($digits[5]) && $digits[5] > 0)
        $string .= $setki[$digits[5]] . ' ';
    if ($i > 4 && isset($digits[4]) && $digits[4] > 1)
        $string .= $dziesiatki[$digits[4]] . ' ';
    elseif ($i > 4 && isset($digits[4]) && $digits[4] == 1 && isset($digits[3]))
        $string .= $nastki[$digits[3]] . ' ';
    if ($i > 3 && isset($digits[3]) && $digits[3] > 0 && isset($digits[4]) && $digits[4] != 1)
        $string .= $jednosci[$digits[3]] . ' ';

    $tmpStr = substr(strrev($digits), 0, -3);
    if (strlen($tmpStr) > 0) {
        $tmpInt = (int)$tmpStr;
        if ($tmpInt == 1)
            $string .= $tysiace[0] . ' ';
        elseif (($tmpInt % 10 > 1 && $tmpInt % 10 < 5) && ($tmpInt < 10 || $tmpInt > 20))
            $string .= $tysiace[1] . ' ';
        else
            $string .= $tysiace[2] . ' ';
    }

    if ($i > 2 && isset($digits[2]) && $digits[2] > 0)
        $string .= $setki[$digits[2]] . ' ';
    if ($i > 1 && isset($digits[1]) && $digits[1] > 1)
        $string .= $dziesiatki[$digits[1]] . ' ';
    elseif ($i > 1 && isset($digits[1]) && $digits[1] == 1 && isset($digits[0]))
        $string .= $nastki[$digits[0]] . ' ';
    if (isset($digits[0]) && $digits[0] > 0 && isset($digits[1]) && $digits[1] != 1)
        $string .= $jednosci[$digits[0]] . ' ';

    return trim($string);
}

/**
 * Kwota słownie - pełna z złotymi i groszami
 */
function slownie($kwota) {
    $zl = ['złotych', 'złoty', 'złote'];
    $gr = ['groszy', 'grosz', 'grosze'];

    $kwota = str_replace(' ', '', $kwota);
    $kwota = str_replace('zł', '', $kwota);
    $kwota = trim($kwota);

    $kwotaArr = explode(',', $kwota);
    $zlote_val = (int)($kwotaArr[0] ?? 0);
    $grosze_val = (int)($kwotaArr[1] ?? 0);

    // Odmiana złotych
    $zlote = odmien($zlote_val, $zl);
    $grosze = odmien($grosze_val, $gr);

    $result = d2w($zlote_val) . ' ' . $zlote;
    if ($grosze_val > 0) {
        $result .= ' ' . d2w($grosze_val) . ' ' . $grosze;
    }

    return $result;
}

/**
 * Odmiana polska (1/2-4/5+)
 */
function odmien($n, $formy) {
    $n = abs((int)$n);
    if ($n == 1) return $formy[1];
    $mod10 = $n % 10;
    $mod100 = $n % 100;
    if ($mod10 >= 2 && $mod10 <= 4 && ($mod100 < 12 || $mod100 > 14)) return $formy[2];
    return $formy[0];
}

/**
 * Sformatuj kwotę z PLN
 */
function format_kwota($kwota) {
    if (empty($kwota)) return '0,00 zł';
    // Jeśli już zawiera "zł", zwróć jak jest
    if (strpos($kwota, 'zł') !== false) return $kwota;
    // Zamień kropkę na przecinek
    $kwota = str_replace('.', ',', $kwota);
    return $kwota . ' zł';
}

/**
 * Parsuj kwotę z tekstu na float
 */
function parse_kwota($str) {
    $str = str_replace(['zł', ' ', "\xc2\xa0"], '', $str);
    $str = str_replace(',', '.', trim($str));
    return (float)$str;
}

/**
 * Status faktury - wyświetl badge
 */
function status_badge($status) {
    $status = trim($status);
    $class = 'secondary';

    if (stripos($status, 'NIEROZLICZONA') !== false) {
        $class = 'warning';
    } elseif (stripos($status, 'CZĘŚCIOWO') !== false) {
        $class = 'warning';
    } elseif (stripos($status, 'ROZLICZONA') !== false) {
        $class = 'success';
    }

    return '<span class="badge bg-' . $class . '">' . e($status) . '</span>';
}

/**
 * Formatuj datę z formatu YYYY-MM-DD na polski
 */
function format_date($date) {
    if (empty($date) || $date === '0000-00-00') return '-';
    $ts = strtotime($date);
    if ($ts === false) return e($date);
    return date('d.m.Y', $ts);
}

/**
 * Generuj numer klienta z ID (np. 1 → "0001", 530 → "0530")
 */
function nr_klienta($id) {
    return str_pad((int)$id, 4, '0', STR_PAD_LEFT);
}

/**
 * Czytaj plik admin/*.txt i zwróć treść (z obsługą HTML)
 * Pliki mogą być w CP1250, Windows-1252 lub UTF-8 (edytowane na Windows)
 */
function read_admin_text($filename, $min_length = 15) {
    $file = IBOK_ADMIN_DIR . '/' . basename($filename);
    if (!file_exists($file)) return '';
    $content = @file_get_contents($file);
    if ($content === false) return '';
    $content = convert_to_utf8($content);
    if (mb_strlen(strip_tags(trim($content))) < $min_length) return '';
    return $content;
}

/**
 * Konwertuj tekst z nieznanego kodowania Windows na UTF-8
 * Obsługuje: UTF-8 (z/bez BOM), CP1250, Windows-1252, ISO-8859-2
 * Nie wymaga mbstring - działa na czystym PHP z iconv
 */
function convert_to_utf8($content) {
    if (empty($content)) return '';

    // Usuń BOM (UTF-8 BOM: EF BB BF)
    if (substr($content, 0, 3) === "\xEF\xBB\xBF") {
        $content = substr($content, 3);
    }

    // Sprawdź czy to poprawny UTF-8 (bez mbstring)
    if (is_valid_utf8($content)) {
        return $content;
    }

    // Nie jest UTF-8 - konwertuj z CP1250 (polskie Windows)
    $converted = @iconv('CP1250', 'UTF-8//IGNORE', $content);
    if ($converted !== false && strlen($converted) > 0) {
        return $converted;
    }

    // Fallback: Windows-1252
    $converted = @iconv('Windows-1252', 'UTF-8//IGNORE', $content);
    if ($converted !== false && strlen($converted) > 0) {
        return $converted;
    }

    // Fallback: ISO-8859-2 (polskie Linux)
    $converted = @iconv('ISO-8859-2', 'UTF-8//IGNORE', $content);
    if ($converted !== false && strlen($converted) > 0) {
        return $converted;
    }

    return $content;
}

/**
 * Sprawdź czy string jest poprawnym UTF-8 (bez zależności od mbstring)
 */
function is_valid_utf8($str) {
    // preg_match z modyfikatorem 'u' (UTF-8) zwraca false dla nie-UTF-8
    return (bool) preg_match('//u', $str);
}

/**
 * Tooltip z ikoną "?" - zwraca HTML z ikoną i dymkiem Bootstrap
 */
function ibok_tooltip($text) {
    return ' <i class="bi bi-question-circle text-muted" data-bs-toggle="tooltip" data-bs-placement="top" title="' . e($text) . '"></i>';
}

/**
 * Zwijana sekcja pomocy - collapsible info block
 */
function ibok_help_section($id, $title, $content) {
    return '<div class="ibok-help mb-3">'
         . '<a class="btn btn-sm btn-outline-info" data-bs-toggle="collapse" href="#help_' . $id . '">'
         . '<i class="bi bi-info-circle"></i> ' . e($title)
         . '</a>'
         . '<div class="collapse mt-2" id="help_' . $id . '">'
         . '<div class="card card-body bg-light border-info small">' . $content . '</div>'
         . '</div></div>';
}

/**
 * Sprawdź czy funkcja jest włączona w cfg/features.cfg
 */
function ibok_feature(string $name): bool {
    static $features = null;
    if ($name === '__reset__') { $features = null; return false; }
    if ($features === null) {
        $file = IBOK_CFG_DIR . '/features.cfg';
        $features = file_exists($file) ? (array)@json_decode(file_get_contents($file), true) : [];
    }
    return !empty($features[$name]);
}

/**
 * Pobierz wartość ustawienia z cfg/features.cfg (nie-bool)
 */
function ibok_setting(string $name, $default = null) {
    static $settings = null;
    if ($settings === null) {
        $file = IBOK_CFG_DIR . '/features.cfg';
        $settings = file_exists($file) ? (array)@json_decode(file_get_contents($file), true) : [];
    }
    return $settings[$name] ?? $default;
}

/**
 * Pobierz najwyższą prędkość z urządzeń klienta (vMac)
 *
 * Używane gdy klient nie ma prędkości w karcie usera (U_PASMO*),
 * a prędkości są przypisane na urządzeniach.
 *
 * @param array $devices Tablica urządzeń z vbk_read_mac()
 * @return array ['dl_dzien'=>string, 'ul_dzien'=>string, 'dl_noc'=>string, 'ul_noc'=>string]
 */
function get_max_device_speed(array $devices): array {
    $best = ['dl_dzien' => '', 'ul_dzien' => '', 'dl_noc' => '', 'ul_noc' => ''];
    $best_val = 0;

    foreach ($devices as $dev) {
        if (!empty($dev['wylaczony']) && $dev['wylaczony'] !== '0') continue;
        $dl = $dev['dl_dzien'] ?? '';
        if ($dl === '' || $dl === '0') continue;
        $num = (float)preg_replace('/[^0-9.,]/', '', str_replace(',', '.', $dl));
        if (stripos($dl, 'Gb') !== false) $num *= 1000;
        if ($num > $best_val) {
            $best_val = $num;
            $best['dl_dzien'] = $dl;
            $best['ul_dzien'] = $dev['ul_dzien'] ?? '';
            $best['dl_noc']   = $dev['dl_noc'] ?? '';
            $best['ul_noc']   = $dev['ul_noc'] ?? '';
        }
    }

    return $best;
}

/**
 * Zapisz features.cfg z obsługą błędów zapisu
 *
 * @return string|true true jeśli OK, string z komunikatem błędu
 */
function ibok_save_features(array $data) {
    $file = IBOK_CFG_DIR . '/features.cfg';
    $dir = dirname($file);

    if (!is_dir($dir)) {
        @mkdir($dir, 0755, true);
    }
    if (!is_writable($dir)) {
        return __('features.error_dir_not_writable', ['dir' => $dir]);
    }
    if (file_exists($file) && !is_writable($file)) {
        return __('features.error_file_not_writable', ['file' => basename($file)]);
    }

    $result = @file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX);
    if ($result === false) {
        return __('features.error_write_failed', [
            'hint' => 'chmod 664 ' . $file . ' && chown apache:apache ' . $file
        ]);
    }
    // Reset cache
    ibok_feature('__reset__');
    return true;
}

/**
 * Czy pokazać prędkość nocną klienta?
 * Tak tylko gdy noc jest ustawiona (download niepusty, != '0') ORAZ różni się
 * od prędkości dziennej. PYXIS dla klientów z jedną prędkością na całą dobę
 * zostawia noc pustą albo duplikuje wartość dzienną — w obu przypadkach nie
 * pokazujemy osobnych wierszy nocnych (byłyby puste lub zdublowane).
 */
function ibok_has_night_speed($dl_dzien, $ul_dzien, $dl_noc, $ul_noc) {
    $dl_noc = trim((string)$dl_noc);
    if ($dl_noc === '' || $dl_noc === '0') {
        return false;
    }
    if ($dl_noc === trim((string)$dl_dzien) && trim((string)$ul_noc) === trim((string)$ul_dzien)) {
        return false;
    }
    return true;
}
