<?php
$zroot = isset($_SESSION["zdir"]) ? $_SESSION["zdir"] : '';

function left($str, $len) {
    return substr($str, 0, $len);
}

function right($str, $len) {
    return substr($str, -$len);
}

function val($v) {
    global $conn;
    return "'" . mysqli_real_escape_string($conn, $v) . "'";
}

// NOTE: When $redirectUrl is passed, the page navigation happens only AFTER the
// SweetAlert2 popup has actually shown and closed (via the promise returned by
// Swal.fire()). This avoids the old bug where a fixed header("refresh:1;...")
// could fire before the alert finished rendering on heavier pages, making the
// alert appear to "not show" on save. If $redirectUrl is omitted, behavior is
// unchanged (caller is expected to redirect itself, e.g. via header()).
//
// IMPORTANT: these functions are called on the POST-success response path,
// which is a bare `<script>...</script>` fragment — includes/linkshead.php
// (the only place jQuery/SweetAlert2 CDN tags are loaded) is never included
// on this path. If SweetAlert2 isn't already loaded in the current document,
// `Swal` is undefined and calling Swal.fire() throws a ReferenceError,
// silently killing the script before the redirect ever runs and leaving the
// user stuck on a blank page with no confirmation. _swalFireOrLoad() guards
// against that by loading the CDN script on demand before firing, with a
// plain redirect fallback if the CDN can't be reached at all.
function _swalFireOrLoad($jsCall, $fallbackRedirectJs) {
    return '<script>(function(){
        function _fire(){ ' . $jsCall . ' }
        if (typeof Swal !== "undefined") { _fire(); }
        else {
            var _s = document.createElement("script");
            _s.src = "https://cdn.jsdelivr.net/npm/sweetalert2@11";
            _s.onload = _fire;
            _s.onerror = function(){ ' . $fallbackRedirectJs . ' };
            document.head.appendChild(_s);
        }
    })();</script>';
}

function insmess($redirectUrl = null) {
    $r = $redirectUrl !== null ? json_encode((string)$redirectUrl) : 'null';
    $call = 'var _r=' . $r . ';Swal.fire({icon:"success",title:"Saved!",text:"Record saved successfully.",timer:1800,showConfirmButton:false,timerProgressBar:true}).then(function(){ if(_r) window.location.href=_r; });';
    $fallback = 'if(' . $r . ') window.location.href=' . $r . ';';
    echo _swalFireOrLoad($call, $fallback);
}

function updmess($redirectUrl = null) {
    $r = $redirectUrl !== null ? json_encode((string)$redirectUrl) : 'null';
    $call = 'var _r=' . $r . ';Swal.fire({icon:"success",title:"Updated!",text:"Record updated successfully.",timer:1800,showConfirmButton:false,timerProgressBar:true}).then(function(){ if(_r) window.location.href=_r; });';
    $fallback = 'if(' . $r . ') window.location.href=' . $r . ';';
    echo _swalFireOrLoad($call, $fallback);
}

function delmess($redirectUrl = null) {
    $r = $redirectUrl !== null ? json_encode((string)$redirectUrl) : 'null';
    $call = 'var _r=' . $r . ';Swal.fire({icon:"success",title:"Deleted!",text:"Record deleted successfully.",timer:1800,showConfirmButton:false,timerProgressBar:true}).then(function(){ if(_r) window.location.href=_r; });';
    $fallback = 'if(' . $r . ') window.location.href=' . $r . ';';
    echo _swalFireOrLoad($call, $fallback);
}

// Generic error alert for bare POST-response paths (e.g. server-side
// validation rejections before the normal insert/update). Same Swal-not-
// loaded hazard as insmess/updmess/delmess, so it goes through the same
// on-demand loader.
function errmess($title, $text, $redirectUrl = null) {
    $r  = $redirectUrl !== null ? json_encode((string)$redirectUrl) : 'null';
    $t  = json_encode((string)$title);
    $tx = json_encode((string)$text);
    $call = 'var _r=' . $r . ';Swal.fire({icon:"error",title:' . $t . ',text:' . $tx . ',confirmButtonColor:"#2563eb"}).then(function(){ if(_r) window.location.href=_r; });';
    $fallback = 'if(' . $r . ') window.location.href=' . $r . ';';
    echo _swalFireOrLoad($call, $fallback);
}

function browse($v) {
    $msg = addslashes(print_r($v, true));
    echo '<script>document.addEventListener("DOMContentLoaded",function(){Swal.fire({icon:"warning",title:"Notice",text:"' . $msg . '",confirmButtonColor:"#2563eb"});});</script>';
}

function getzdates() {
    global $conn, $dbname;
    $yr = isset($_SESSION["tit_" . $dbname]) ? $_SESSION["tit_" . $dbname] : '';
    $q  = mysqli_query($conn,
        "SELECT DATE_FORMAT(`startdate`,'%d-%m-%Y') as sdt,
                DATE_FORMAT(`lastdate`,'%d-%m-%Y') as edt
         FROM `compyear`
         WHERE `finyear`='" . mysqli_real_escape_string($conn, $yr) . "'"
    );
    if ($q && mysqli_num_rows($q) > 0) {
        $r = mysqli_fetch_assoc($q);
        return [$r['sdt'], $r['edt']];
    }
    return ['', ''];
}

function audituser() {
    global $dbname;
    return isset($_SESSION["username_" . $dbname]) ? $_SESSION["username_" . $dbname] : '';
}

function monthname($m) {
    $months = [
        '', 'January', 'February', 'March', 'April', 'May', 'June',
        'July', 'August', 'September', 'October', 'November', 'December'
    ];
    return isset($months[(int)$m]) ? $months[(int)$m] : '';
}

// Legacy numeric formatter used throughout trbal_fr.php's Trial Balance
// columns (rajnumformat($amt) / rajnumformat($amt, 2)) — it was referenced
// dozens of times in that report but never actually defined anywhere in the
// codebase, causing "Call to undefined function rajnumformat()". Mirrors
// number_format()'s behavior (comma thousands separator, fixed decimals),
// which is what every other report in this app already uses for amounts.
function rajnumformat($val, $dec = 2) {
    return number_format((float) $val, $dec);
}

function format_date($val) {

    if ($val != "0000-00-00" && $val != "") {
        $nt = date('Y-m-d', strtotime($val));
        $newdate = date("d-m-Y", strtotime($nt));

        return $newdate;
    }
}


function rsword($number) {

    if (($number < 0) || ($number > 999999999)) {

        throw new Exception("Number is out of range");
    }

    $Gn = floor($number / 100000);  /* Millions (giga) */

    $number -= $Gn * 100000;

    $kn = floor($number / 1000);     /* Thousands (kilo) */

    $number -= $kn * 1000;

    $Hn = floor($number / 100);      /* Hundreds (hecto) */

    $number -= $Hn * 100;

    $Dn = floor($number / 10);       /* Tens (deca) */

    $n = $number % 10;               /* Ones */

    $res = "";

    if ($Gn) {
        $res .= rsword($Gn) . " Lakh";
    }

    if ($kn) {
        $res .= (empty($res) ? "" : " ") .
                rsword($kn) . " Thousand";
    }

    if ($Hn) {
        $res .= (empty($res) ? " " : " ") .
                rsword($Hn) . " Hundred";
    }

    $ones = array("", "One", "Two", "Three", "Four", "Five", "Six",
        "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
        "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eightteen",
        "Nineteen");

    $tens = array("", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty",
        "Seventy", "Eigthy", "Ninety");

    if ($Dn || $n) {

        if (!empty($res)) {

            $res .= " And ";
        }

        if ($Dn < 2) {

            $res .= $ones[$Dn * 10 + $n];
        } else {

            $res .= $tens[$Dn];

            if ($n) {

                $res .= "-" . $ones[$n];
            }
        }
    }

    if (empty($res)) {

        $res = "zero";
    }

    return $res;
}

?>
