<?php

use App\Models\Account;
use App\Models\AccountAddress;
use App\Models\Bucket;
use App\Models\Company;
use App\Models\LibrarySetting\BookFormates;
use App\Models\LibrarySetting\LibrarianAuthors;
use App\Models\LibrarySetting\LibrarianGernes;
use App\Models\LibrarySetting\LibrarianPublishers;
use App\Models\Library\BookApi;
use App\Models\MenuModelPermission;
use App\Models\StorageSetting;
use App\Models\AdvanceSetting;
use App\Models\CompanyLicence;
use App\Models\AccountLicense;
use App\Models\AcReceipt;
use App\Models\AcReceiptDetail;
use App\Models\Language;
use App\Models\Library\BookIssue;
use App\Models\Library\BookIssueDetail;
use App\Models\Library\LibraryCard;
use App\Models\LibrarySetting\LibrarianTags;
use App\Models\LibrarySetting\MembershipPlan;
use App\Models\LibrarySetting\Stream;
use App\Models\LibrarySetting\Translators;
use App\Models\OpdBookingDetail;
use App\Models\PaymentVoucher;
use App\Models\Product;
use App\Models\ProductLocation;
use App\Models\Purchase\PurchaseInvoiceDetails;
use App\Models\Purchase\PurchaseOthersTransaction;
use App\Models\SaleInvoiceDetail;
use App\Models\SaleOthersTransaction;
use App\Models\Sales\SaleReturnDetails;
use App\Models\Sales\SaleReturns;
use App\Models\Stock;
use App\Models\StudyMaterial;
use App\Models\User;
use App\Models\VoucherType;
use App\Models\Website\PublicContent;
use GuzzleHttp\Client;
use Spatie\Permission\Models\Permission;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Carbon\Carbon;
use GuzzleHttp\Handler\Proxy;

if (!function_exists('uploadImage')) {
    function uploadImage($path, $image, $old_image = '')
    {
        $bucket = BucketData();

        if (!empty($bucket)) {
            $today       = \Carbon\Carbon::now()->toDateString();
            $renewalDate = \Carbon\Carbon::parse($bucket->next_renewal_date);

            if ($today > $renewalDate) {
                $return['message'] = "S3 Bucket has been expired!";
                $return['status'] = false;

                return $return;
            }

            $ImageDomain = $bucket->main_folder ?? '';

            config([
                'filesystems.disks.s3.key'    => $bucket->access_key ?? '',
                'filesystems.disks.s3.secret' => $bucket->secret_key ?? '',
                'filesystems.disks.s3.region' => $bucket->region ?? '',
                'filesystems.disks.s3.bucket' => $bucket->bucket_name ?? '',
            ]);
            $allowedExtensions      = explode(',', $bucket->storage_validation ?? '');
            $storageMaxUploadSizeKB = $bucket->storage_max_upload_size ?? '';
        } else {
            $ImageDomain       = $allowedExtensions = $storageMaxUploadSizeKB = '';
            $allowedExtensions = [];

            $return['message'] = "S3 Bucket credentials not found!";
            $return['status']  = false;

            return $return;
        }

        if ($old_image != '') {
            Storage::disk('s3')->delete($ImageDomain . '/' . $old_image);
        }

        if (!in_array($image->extension(), $allowedExtensions)) {
            $return['message'] = "Invalid file extension. Allowed extensions: " . implode(', ', $allowedExtensions);
            $return['status']  = false;
            return $return;
        }
        if ($image->getSize() > $storageMaxUploadSizeKB * 1024) {
            $return['message'] = "File size exceeds the allowed limit of {$storageMaxUploadSizeKB} KB.";
            $return['status']  = false;
            return $return;
        }

        $ImageName = time() . '.' . $image->extension();
        $ImagePath = Storage::disk('s3')->put($ImageDomain . '/' . $path, $image, 'public', [
            'ContentDisposition' => 'attachment',
        ]);

        if($ImagePath){
            $image_name = explode($ImageDomain . '/', $ImagePath);

            $return['file_name'] = $image_name[1];

            $return['status']    = true;
            return $return;
        }else{
            $return['message'] = "File Not Upload ";
            $return['status'] = false;
            return $return;
        }
    }
}

if (!function_exists('deleteImage')) {
    function deleteImage($old_image)
    {
        $bucket = BucketData();
        if (!empty($bucket)) {
            $ImageDomain = $bucket->main_folder;

            config([
                'filesystems.disks.s3.key'    => $bucket->access_key,
                'filesystems.disks.s3.secret' => $bucket->secret_key,
                'filesystems.disks.s3.region' => $bucket->region,
                'filesystems.disks.s3.bucket' => $bucket->bucket_name,
            ]);
            $allowedExtensions      = explode(',', $bucket->storage_validation);
            $storageMaxUploadSizeKB = $bucket->storage_max_upload_size;
        }

        if ($old_image != '') {
            Storage::disk('s3')->delete($ImageDomain . '/' . $old_image);
        }

        $return['status'] = true;
        return $return;
    }
}

if (!function_exists('BucketData')) {
    function BucketData()
    {
        $BucketData = \Session::get('BucketData');
        if($BucketData)
        {
            $BucketData = $BucketData;
        }
        else
        {

            $librarianGernes = \Session::get('SessionBucketData');

            $BucketData      = StorageSetting::select([
                'main_folder',
                'access_key',
                'secret_key',
                'region',
                'bucket_name',
                'storage_validation',
                'storage_max_upload_size',
                'next_renewal_date',
            ])
            ->where(['storage_type' => 's3_bucket'])->first();
        }

        return $BucketData;
    }
}

if (!function_exists('getTempUrl')) {
    function getTempUrl($image)
    {
        if($image)
        {

        $bucket = BucketData();
        if (!empty($bucket)) {
            config([
                'filesystems.disks.s3.key'    => $bucket->access_key,
                'filesystems.disks.s3.secret' => $bucket->secret_key,
                'filesystems.disks.s3.region' => $bucket->region,
                'filesystems.disks.s3.bucket' => $bucket->bucket_name,
            ]);

            $temporarySignedUrl = \Storage::disk('s3')->temporaryUrl($bucket->main_folder . '/' . $image, now()->addMinutes(10));

            return $temporarySignedUrl;
        } else {
            return '';
        }
    }else{
        return '';
    }
    }
}

if (!function_exists('getPermanentUrl')) {
    function getPermanentUrl($image)
    {
        $bucket = BucketData();
        if (!empty($bucket)) {
            config([
                'filesystems.disks.s3.key'    => $bucket->access_key,
                'filesystems.disks.s3.secret' => $bucket->secret_key,
                'filesystems.disks.s3.region' => $bucket->region,
                'filesystems.disks.s3.bucket' => $bucket->bucket_name,
            ]);

            $permanentUrl = \Storage::disk('s3')->url($bucket->main_folder . '/' . $image);

            return $permanentUrl;
        } else {
            return '';
        }
    }
}

if (!function_exists('getBucketFile')) {
    function getBucketFile($image)
    {
        $bucket = BucketData();

        if (!empty($bucket)) {
            config([
                'filesystems.disks.s3.key'    => $bucket->access_key,
                'filesystems.disks.s3.secret' => $bucket->secret_key,
                'filesystems.disks.s3.region' => $bucket->region,
                'filesystems.disks.s3.bucket' => $bucket->bucket_name,
            ]);

            return Storage::disk('s3')->get($image);
        } else {
            return '';
        }
    }
}

if (!function_exists('getComapnyName')) {
    function getComapnyName()
    {
        $HeadOfficeData = \Session::get('SessionHeadOfficeData') ?? [];

        return $HeadOfficeData;
    }
}
/*
if (!function_exists('nameByPermisson')) {
    function nameByPermisson($Name)
    {
        $permissions = Permission::select(['id', 'per_name', 'name'])->where(['per_name' => $Name])->get();
        return $permissions;
    }
}*/


/*if (!function_exists('MenuPermission')) {
    function MenuPermission($name)
    {
        $permissions = MenuModelPermission::select(['id', 'menu_name', 'status'])->where(['menu_name' => $name])->first();
        return $permissions;
    }
}*/

if (!function_exists('getCategory')) {
    function getCategory()
    {
        $librarianGernes = \Session::get('librarianGernes');

        return $librarianGernes;
    }
}
/*************************Book Api Data ************************/
if (!function_exists('getBookApi')) {
    function getBookApi()
    {
        $BookApiData = \Session::get('BookApiData');

        return $BookApiData;
    }
}


/****************************OPen Library Api Inegration *********************/
if (!function_exists('openApigetDta')) {
    function openApigetDta($query)
    {
        $BookApiData = getBookApi();
        //dd($BookApiData);
        $url = $BookApiData->base_url . '/' . $BookApiData->veriables . '/' . $query . '.' . $BookApiData->exyention;
        $guzzle_client = new \GuzzleHttp\Client();

        $response = $guzzle_client->get($url);
        $response_body = json_decode($response->getBody()->getContents(), true);
        return $response_body;
    }
}
/*******************Get Author ***************/
if (!function_exists('getAuthor')) {
    function getAuthor($query)
    {
        $authorData = LibrarianAuthors::select(['id', 'first_name'])->where(['first_name' => trim($query)])->first();
        if ($authorData) {
            return $authorData->id;
        } else {
            $authorData = LibrarianAuthors::create(['first_name' => generateStringFormate(trim($query))]);
            return $authorData->id;
        }

    }
}

/*******************Get Publisher ***************/
if (!function_exists('getPublisher')) {
    function getPublisher($query)
    {
        $publisherData = LibrarianPublishers::select(['id', 'name'])->where(['name' => trim($query)])->first();
        if ($publisherData) {
            return $publisherData->id;
        } else {
            $publisherData = LibrarianPublishers::create(['name' => generateStringFormate(trim($query))]);
            return $publisherData->id;
        }

    }
}

/*******************Get Book Formate ***************/
if (!function_exists('getBookFormate')) {
    function getBookFormate($query)
    {
        $bookFormateData = BookFormates::select(['id', 'formate_name'])->where(['formate_name' => trim($query)])->first();
        if ($bookFormateData) {
            return $bookFormateData->id;
        } else {
            $bookFormateData = BookFormates::create(['formate_name' => generateStringFormate(trim($query))]);
            return $bookFormateData->id;
        }

    }
}
/*********************** Third party Api  To Image Get Into Over Server *******************************/
if (!function_exists('getImagesStore')) {
    function getImagesStore($isbn_no, $type, $imageUrl)
    {

        $path = "uploads/books/" . $isbn_no . "/" . "cover_image/" . $type . "";

        // Create the directory if it doesn't exist
        if (!is_dir($path)) {
            mkdir($path, 0777, true);
        }

        // Extract the filename from the URL
        //$filename = basename($imageUrl);

        // Generate the local file path
        //$localFilePath = $path . $filename;

        // Download the image and save it to the local file
        if ($filename = downloadAndStoreImage($imageUrl, $path)) {
            $datas = uploadImage($path, $filename);
            if ($datas) {
                //unlink($localFilePath);
                return $datas;
            }
            return $datas;
        } else {
            return true;
        }

    }
}



if (!function_exists('uploadImages')) {
    function uploadImages($path, $image, $isbn_no, $type)
    {
        $bucket = BucketData();

        if (!empty($bucket)) {
            $ImageDomain = $bucket->main_folder;

            config([
                'filesystems.disks.s3.key' => $bucket->access_key,
                'filesystems.disks.s3.secret' => $bucket->secret_key,
                'filesystems.disks.s3.region' => $bucket->region,
                'filesystems.disks.s3.bucket' => $bucket->bucket_name,
            ]);
            $allowedExtensions = explode(',', $bucket->storage_validation);
            $storageMaxUploadSizeKB = $bucket->storage_max_upload_size;
        } else {
            $ImageDomain = $allowedExtensions = $storageMaxUploadSizeKB = '';
            $allowedExtensions = [];
        }

        $extension = pathinfo($image, PATHINFO_EXTENSION);
        // $ImageName = time() . '.' . $image->extension();
        $new = $isbn_no . '_' . $type;
        $imageName = $new . '.' . $extension;

        $ImagePath = Storage::disk('s3')->put($ImageDomain . '/' . $path, $imageName, 'public', [
            'ContentDisposition' => 'attachment',
        ]);
        $image_name = explode($ImageDomain . '/', $ImagePath);
        dd($image_name);

        return $image_name[1];
    }
}

if (!function_exists('formatPermissionsText')) {
    function formatPermissionsText($inputText, $remove_text = '')
    {
        $formattedText = ucwords(str_replace('-', ' ', $inputText));

        if ($remove_text != '') {
            $wordArray = explode(' ', $formattedText);
            $wordsToRemove = explode(' ', $remove_text);
            $filteredArray = array_filter($wordArray, function ($word) use ($wordsToRemove) {
                return !in_array($word, $wordsToRemove);
            });
            $formattedText = implode(' ', $filteredArray);
        }

        return $formattedText;
    }
}


if (!function_exists('downloadAndStoreImage')) {
    function downloadAndStoreImage($url, $destinationPath)
    {
        $client = new Client();
        $response = $client->get($url);

        // Generate a unique filename for the local storage
        $filename = Str::random(40) . '.jpg'; // You can adjust the filename format if needed

        // Store the image in the local storage
        Storage::put($destinationPath . '/' . $filename, $response->getBody());

        return $filename;
    }
}

if (!function_exists('storageExtensions')) {
    function storageExtensions()
    {
        return array(
            '3dmf' => '3dmf',
            '3dm' => '3dm',
            'avi' => 'avi',
            'ai' => 'ai',
            'bin' => 'bin',
            'bin' => 'bin',
            'bmp' => 'bmp',
            'cab' => 'cab',
            'c' => 'c',
            'c++' => 'c++',
            'class' => 'class',
            'css' => 'css',
            'csv' => 'csv',
            'cdr' => 'cdr',
            'doc' => 'doc',
            'dot' => 'dot',
            'docx' => 'docx',
            'dwg' => 'dwg',
            'eps' => 'eps',
            'exe' => 'exe',
            'gif' => 'gif',
            'gz' => 'gz',
            'gtar' => 'gtar',
            'flv' => 'flv',
            'fh4' => 'fh4',
            'fh5' => 'fh5',
            'fhc' => 'fhc',
            'help' => 'help',
            'hlp' => 'hlp',
            'html' => 'html',
            'htm' => 'htm',
            'ico' => 'ico',
            'imap' => 'imap',
            'inf' => 'inf',
            'jpe' => 'jpe',
            'jpeg' => 'jpeg',
            'jpg' => 'jpg',
            'js' => 'js',
            'java' => 'java',
            'latex' => 'latex',
            'log' => 'log',
            'm3u' => 'm3u',
            'midi' => 'midi',
            'mid' => 'mid',
            'mov' => 'mov',
            'mp3' => 'mp3',
            'mpeg' => 'mpeg',
            'mpg' => 'mpg',
            'mp2' => 'mp2',
            'ogg' => 'ogg',
            'phtml' => 'phtml',
            'php' => 'php',
            'pdf' => 'pdf',
            'pgp' => 'pgp',
            'png' => 'png',
            'pps' => 'pps',
            'ppt' => 'ppt',
            'pptx' => 'pptx',
            'ppz' => 'ppz',
            'pot' => 'pot',
            'ps' => 'ps',
            'qt' => 'qt',
            'qd3d' => 'qd3d',
            'qd3' => 'qd3',
            'qxd' => 'qxd',
            'rar' => 'rar',
            'ra' => 'ra',
            'ram' => 'ram',
            'rm' => 'rm',
            'rtf' => 'rtf',
            'spr' => 'spr',
            'sprite' => 'sprite',
            'stream' => 'stream',
            'swf' => 'swf',
            'svg' => 'svg',
            'sgml' => 'sgml',
            'sgm' => 'sgm',
            'tar' => 'tar',
            'tiff' => 'tiff',
            'tif' => 'tif',
            'tgz' => 'tgz',
            'tex' => 'tex',
            'txt' => 'txt',
            'vob' => 'vob',
            'wav' => 'wav',
            'wrl' => 'wrl',
            'wrl' => 'wrl',
            'xla' => 'xla',
            'xls' => 'xls',
            'xls' => 'xls',
            'xlc' => 'xlc',
            'xml' => 'xml',
            'xlsx' => 'xlsx',
            'zip' => 'zip',
            'zip' => 'zip',
        );
    }
}
if (!function_exists('daysOfWeek')) {
    function daysOfWeek($day = null)
    {
        $values = [
            '1' => 'Monday',
            '2' => 'Tuesday',
            '3' => 'Wednesday',
            '4' => 'Thursday',
            '5' => 'Friday',
            '6' => 'Saturday',
            '7' => 'Sunday',
        ];
        return isset($day) && $day <= 7 && $day >= 1 ? $values[$day] : $values;
    }
}
if (!function_exists('months')) {
    function months($day = null)
    {
        $values = [
            '1' => 'January',
            '2' => 'February',
            '3' => 'March',
            '4' => 'April',
            '5' => 'May',
            '6' => 'June',
            '7' => 'July',
            '8' => 'August',
            '9' => 'September',
            '10' => 'October',
            '11' => 'November',
            '12' => 'December',
        ];
        return isset($day) && $day <= 7 && $day >= 1 ? $values[$day] : $values;
    }
}

if (!function_exists('matchChecked')) {
    function matchChecked($param1, $param2)
    {
        return $param1 == $param2 ? ' checked="checked" ' : '';
    }
}

if (!function_exists('matchSelected')) {
    function matchSelected($param1, $param2)
    {
        return $param1 == $param2 ? ' selected="selected" ' : '';
    }
}
if (!function_exists('formatedDate')) {
    function formatedDate($date = '')
    {
        if ($date == NULL || $date == '' || $date == '0000-00-00' || (!isDate($date) && \DateTime::createFromFormat('Y-m-d H:i:s', $date) === false)) {
            return '';
        }

        $company_data = \Session::get('company_data');

        $date_format  = $company_data['date_format'] ?? "m-d-Y";
        $formatedDate = date($date_format, strtotime($date));

        return $formatedDate;
    }
    function isDate($date, $format = 'Y-m-d')
    {
        $d = DateTime::createFromFormat($format, $date);
        return ($d && $d->format($format) == $date ? $d : '');
    }
}

if (!function_exists('formatedTime')) {
    function formatedTime($time = '')
    {
        if ($time == '') {
            return '';
        }

        $company_data = \Session::get('company_data');
        $time_zone   = $company_data['time_zone'] ?? "Asia/Kolkata";
        $time_format = $company_data['time_format'] ?? "H:i:s";

        $time         = \Carbon\Carbon::parse($time);
        $formatedTime  = $time->format($time_format);


        return $formatedTime;
    }
}

if (!function_exists('age')) {
    function age($dateOfBirth = '')
    {
        if ($dateOfBirth == '') {
            return '';
        }

        $dob   = date('Y-m-d', strtotime($dateOfBirth));
        $years = Carbon::parse($dob)->age;

        return $years;
    }
}

if (!function_exists('ageInHours')) {
    function ageInHours($dateOfBirth = '')
    {
        if ($dateOfBirth == '') {
            return '';
        }

        $dob    = new DateTime(date('Y-m-d H:i:s', strtotime($dateOfBirth)));
        $today  = new DateTime(date('Y-m-d H:i:s'));
        $diff   = $today->diff($dob);
        $years  = $diff->y * 12 * 30 * 24;
        $months = $diff->m * 30 * 24;
        $days   = $diff->d * 24;
        $hours  = $diff->h;
        $diff = $hours + $days + $months + $years;

        return $diff;
    }
}

if (!function_exists('generateTimezoneList')) {
/**
 * Returns array of timezones
 *
 * CALLING PROCEDURE
 *
 * In Controller call it like this:
 * generateTimezoneList();
 *
 * In View call it like this:
 * generateTimezoneList()
 *
 * @return array
 */
    // function generateTimezoneList(): array
    // {
    //     static $regions = array(
    //         \DateTimeZone::AFRICA,
    //         \DateTimeZone::AMERICA,
    //         \DateTimeZone::ANTARCTICA,
    //         \DateTimeZone::ASIA,
    //         \DateTimeZone::ATLANTIC,
    //         \DateTimeZone::AUSTRALIA,
    //         \DateTimeZone::EUROPE,
    //         \DateTimeZone::INDIAN,
    //         \DateTimeZone::PACIFIC,
    //     );

    //     $timezones = array();

    //     foreach ($regions as $region) {
    //         $timezones = array_merge($timezones, \DateTimeZone::listIdentifiers($region));
    //     }

    //     $timezone_offsets = array();

    //     foreach ($timezones as $timezone) {
    //         $tz = new \DateTimeZone($timezone);
    //         $timezone_offsets[$timezone] = $tz->getOffset(new \DateTime);
    //     }

    //     // sort timezone by timezone name
    //     ksort($timezone_offsets);

    //     $timezone_list = array();

    //     foreach ($timezone_offsets as $timezone => $offset) {
    //         $offset_prefix = $offset < 0 ? '-' : '+';
    //         $offset_formatted = gmdate('H:i', abs($offset));

    //         $pretty_offset = "UTC${offset_prefix}${offset_formatted}";

    //         $t = new \DateTimeZone($timezone);
    //         $c = new \DateTime(null, $t);
    //         $current_time = $c->format('g:i A');

    //         $timezone_list[$timezone] = "$timezone " . $pretty_offset;
    //     }

    //     return $timezone_list;
    // }
}
function convertAmountToWords($amount) {
    $company_data = \Session::get('company_data');
    $currency = $company_data['companies_addresses'];

    $amount       = (int)$amount;
    $formatter    = new NumberFormatter('en_GB',  NumberFormatter::SPELLOUT);
    $textFormat   = $formatter->formatCurrency($amount, ($currency->currency_code ?? "USD")) . PHP_EOL;

    return ucwords(str_replace('-',' ', $textFormat)) . ' ' . ($currency->currency ?? '') . ' Only';
}

function convertDecimelPoint($amount) {
    if(!empty($amount) && $amount ){

        $decimal = is_numeric(\Session::get('decimallength')) ? \Session::get('decimallength') : 2;
        $amount  = number_format($amount, $decimal, '.', '');
    }else{
        $amount = 0;
    }

    return $amount;
}


if (! function_exists('bookLimit')) {
    function bookLimit($student_id,$financial_id)
    {
        $getLibrarycard=LibraryCard::where(['account_id'=>$student_id])->select('membership_id')->first();
        if(isset($getLibrarycard->membership_id))
        {
            $membershipdata=MembershipPlan::find($getLibrarycard->membership_id);
            return  $membershipdata->book_limit;
        }
        else
        {
            return 0;
        }

    }
   }


    /*******************************Book Expire Calculate **************************/
if (! function_exists('bookexpirecalculate')) {
    function bookexpirecalculate($student_id,$financial_id,$issue_date)
    {
        $getLibrarycard=LibraryCard::where(['account_id'=>$student_id])->select('membership_id')->first();
        $getLibrarycard->membership_id;
        $membershipdata=MembershipPlan::find($getLibrarycard->membership_id);
        if($membershipdata)
        {
            return date('Y-m-d', strtotime($issue_date. ' + '.$membershipdata->book_validity.' days'));
        }
        else
        {
            return date('Y-m-d', strtotime($issue_date. ' + 20 days'));
        }
    }
   }

   if(!function_exists('sumIssueBooks'))
{
    function sumIssueBooks($student_id)
    {
        $BookIsue=BookIssue::where('account_id',$student_id)->get();
        $totalqty=0;

        foreach($BookIsue as $issue)
        {
            $qnts=BookIssueDetail::where('book_issue_id',$issue->id)->where('return_status','No')->sum('qnt');
            $totalqty+=$qnts;
        }
        return $totalqty;
    }
}

/*******************Get Category ***************/
if (! function_exists('getBookcategory')) {
    function getBookcategory($query)
    {
        $CategoryData = LibrarianGernes::select(['id','name'])->where(['name'=>trim($query)])->first();
        if($CategoryData)
        {
            return $CategoryData->id;
        }
        else
        {
            $CategoryData = LibrarianGernes::create(['name' => generateStringFormate(trim($query))]);
            return $CategoryData->id;
        }

    }
}

/*******************Get Stream ***************/
if (! function_exists('getBookSteam')) {
    function getBookSteam($query)
    {
        $StreamData = Stream::select(['id','stream_name'])->where(['stream_name'=>trim($query)])->first();
        if($StreamData)
        {
            return $StreamData->id;
        }
        else
        {
            $StreamData = Stream::create(['stream_name' => generateStringFormate(trim($query))]);
            return $StreamData->id;
        }

    }
}

/*******************Get Translator ***************/
if (! function_exists('getBookTranslator')) {
    function getBookTranslator($query)
    {
        $translatorData = Translators::select(['id','translator_name'])->where(['translator_name'=>trim($query)])->first();
        if($translatorData)
        {
            return $translatorData->id;
        }
        else
        {
            $translatorData = Translators::create(['translator_name' => generateStringFormate(trim($query))]);
            return $translatorData->id;
        }

    }
}

/*******************Get Languguage ***************/
if (! function_exists('getBooklanguage')) {
    function getBooklanguage($query)
    {
        $languageData = Language::select(['id','name'])->where(['name'=>trim($query)])->first();
        if($languageData)
        {
            return $languageData->id;
        }
        else
        {
            $languageData = Language::create(['name' => generateStringFormate(trim($query))]);
            return $languageData->id;
        }

    }
}

/*******************Get Tag ***************/
if (! function_exists('getBookTag')) {
    function getBookTag($query)
    {
        $tagData = LibrarianTags::select(['id','tag_name'])->where(['tag_name'=>trim($query)])->first();
        if($tagData)
        {
            return $tagData->id;
        }
        else
        {
            $tagData = LibrarianTags::create(['tag_name' => generateStringFormate(trim($query))]);
            return $tagData->id;
        }

    }
}

if (!function_exists('formatedDateTime')) {
    function formatedDateTime($datetime = '')
    {
        //dd($datetime);
        if ($datetime == '' || $datetime == '0000-00-00 00:00:00') {
            return '';
        }

        $company_data    = \Session::get('company_data');

        $time_format     = $company_data['time_format'] ?? "H:i:s";
        $date_format     = $company_data['date_format'] ?? "m-d-Y";

        // $datetime_format = Company::companyDateTimeFormat();
        $formattedDate   = date($date_format, strtotime($datetime));

        // Only include AM/PM in the time format, not date
        $formattedTime   = date($time_format, strtotime($datetime));

        return $formattedDate .", ". $formattedTime;
    }
}
if (!function_exists('formatedDateTimeForBill')) {
    function formatedDateTimeForBill($datetime = '')
    {
        if ($datetime == '' || $datetime == '0000-00-00 00:00:00') {
            return '';
        }

        $company_data    = \Session::get('company_data');

        $time_format     = $company_data['time_format'] ?? "H:i:s";
        $date_format     = $company_data['date_format'] ?? "m-d-Y";

        // $datetime_format = Company::companyDateTimeFormat();
        $formattedDate   = date($date_format, strtotime($datetime));

        // Only include AM/PM in the time format, not date
        $formattedTime   = date($time_format, strtotime($datetime));

        return $formattedDate .','. $formattedTime;
    }
}


if (!function_exists('yearsToHours')) {
    function yearsToHours($years = '')
    {
        if ($years == '') {
            return '';
        }

        $calculateHours = $years*8760;

        return $calculateHours;
    }
}

if (!function_exists('daysToHours')) {
    function daysToHours($days = '')
    {
        if ($days == '') {
            return '';
        }

        $calculateHours = $days*24;

        return $calculateHours;
    }
}

if (!function_exists('hoursToYears')) {
    function hoursToYears($hours = '')
    {
        if ($hours == '') {
            return '';
        }

        $calculateYears = $hours*0.000114155;

        return number_format($calculateYears);
    }
}

if (!function_exists('hoursToDays')) {
    function hoursToDays($hours = '')
    {
        if ($hours == '') {
            return '';
        }

        $calculateDays = 0.0416667*$hours;

        return number_format($calculateDays);
    }
}

if (!function_exists('generateStringFormate')) {
function generateStringFormate($testString)
{
    $upper = Str::ucfirst(strtolower(trim($testString)));
    return  $upper;
}
}

if (!function_exists('reportDeliveryDate')) {
    function reportDeliveryDate($date, $days)
    {
        $days = $days > 0 ? $days : 0;
        $date = $date != '' ? $date : '';

        if ($date != '' && $days > 0) {
            $date = \Carbon\Carbon::parse($date)->addDays($days);
            return formatedDate($date);
        } else if ($date != '' && $days == 0) {
            return formatedDate($date);
        }
    }
}
if (!function_exists('fileTypes')) {
    function fileTypes($type = null)
    {
        $values = [
            '1' => 'pdf',
            '2' => 'excel',
            '3' => 'jpg',
            '4' => 'png',
            '5' => 'word',
            '6' => 'text',
            '7' => 'audio',
            '8' => 'video',
        ];

        return isset($type) && $type <= 8 && $type >= 1 ? $values[$type] : $values;
    }
}
if (!function_exists('fileCategories')) {
    function fileCategories($type = null)
    {
        $values = [
            '1' => 'general'
        ];

        return isset($type) && $type <= 8 && $type >= 1 ? $values[$type] : $values;
    }
}
if (!function_exists('companyLicenses')) {
    function companyLicenses($id = null)
    {
        if($id != null) {
            $licenses = CompanyLicence::select([
                  'companies_license.license_number',
                  'companies_license_type.license_type_name',
                  'companies_license_type.priority'
                ])
                ->leftjoin('companies_license_type', 'companies_license_type.id', 'companies_license.license_type_id')
                ->where('companies_license.company_id', $id)
                ->where('companies_license_type.show_in_print', '1')
                ->where('companies_license.license_status', 1)
                ->orderBy('companies_license_type.priority','ASC')
                ->get();

            return $licenses;
        }
    }
}
if (!function_exists('accountLicenses')) {
    function accountLicenses($id = null)
    {
        if($id != null) {
            $license = AccountLicense::select('account_licenses.license_number','license_types.name')
                ->leftjoin('license_types', 'license_types.id', 'account_licenses.license_type_id')
                ->where('account_licenses.account_id', $id)
                ->where('license_types.show_in_print', '1')
                ->orderBy('license_types.priority','ASC')
                ->get();

            return $license;
        }
    }
}
if (!function_exists('phpToJsDateFormat')) {
    function phpToJsDateFormat($format = null)
    {
        $values = [
            'Y-m-d'     => 'yyyy-mm-dd',
            'm/d/Y'     => 'mm/dd/yyyy',
            'd-m-Y'     => 'dd-mm-yyyy',
            'm-d-Y'     => 'mm-dd-yyyy',
            'M d, Y'    => 'mmM dd, yyyy',
            'j F Y'     => 'd MMMM yyyy',
            'l, M d, Y' => 'dddd, MMM dd, yyyy',
            'd.m.Y'     => 'dd.mm.yyyy',
            'd/m/Y'     => 'dd/mm/yyyy',
            'F j, Y'    => 'MMMM d, yyyy',
            'd M Y'     => 'dd MMM yyyy'
        ];

        return $values[$format] ?? 'dd-MM-yyyy';
    }
}
if (!function_exists('taxAmountCalculate')) {
    function taxAmountCalculate($tax_percentage, $total_amount)
    {
        return ($tax_percentage / 100) * $total_amount;
    }
}

if (!function_exists('generate_comma_separated_string')) {
 function generate_comma_separated_string(
    array $data,
    array $keys              = [],
    array $keyNames          = [],
    array $elementSeparators = [],
    string $defaultSeparator = ': '
) {
    if (empty($keys)) {
        $filteredData = array_filter($data, function($value) {
            return !empty($value);
        });

        return implode(', ', $filteredData);
    }

    $resultArray = [];

    foreach ($keys as $index => $key) {
        if (array_key_exists($key, $data) && !empty($data[$key])) {
            $separator = $elementSeparators[$key] ?? $defaultSeparator;

            if (!empty($keyNames[$index])) {
                $resultArray[] = $keyNames[$index].$separator.$data[$key];
            } else {
                $resultArray[] = $data[$key];
            }
        }
    }

    return implode(', ', $resultArray);
}
}


    function TransactionCalculationReceiveAmount($invoice_id,$module_code)
    {
        $AcReceipt = AcReceipt::select(['id', 'voucher_id'])
        ->with(['accountReceiptReceivedAmount'])
        ->where(['module_code' => $module_code, 'voucher_id' => $invoice_id])
        ->get();
        $totalReturn = 0;
        if($module_code=="OPD_BOOKING")
        {
            $finalTotal    = OpdBookingDetail::where('opd_booking_id',$invoice_id)->sum('amount','price');
            $discountPrice = SaleOthersTransaction::select('price')->where(['sale_invoice_id'=>$invoice_id,'voucher_type'=>$module_code,'account_id'=>67])->first();
            $roundOffPrice = SaleOthersTransaction::select('price')->where(['sale_invoice_id'=>$invoice_id,'voucher_type'=>$module_code,'account_id'=>110])->first();
        }else{
            $finalTotal    = SaleInvoiceDetail::where('sale_invoice_id',$invoice_id)->sum('total_amount','price');
            $discountPrice = SaleOthersTransaction::select('price')->where(['sale_invoice_id'=>$invoice_id,'account_id'=>67])->first();
            $roundOffPrice = SaleOthersTransaction::select('price')->where(['sale_invoice_id'=>$invoice_id,'account_id'=>110])->first();

            $sale_return_invoice = SaleReturns::select('id')
                    ->where('voucher_type_code', 'SALE_RETURN')
                    ->where('voucher_type_id',$invoice_id)
                    ->first();
            if(isset($sale_return_invoice))
            {
                $totalReturn = SaleReturnDetails::where(['sale_return_invoice_id'=>$sale_return_invoice->id])->sum('total_amount','price');
            }
            
        }


        
        $receivedAmount=0;
        if(isset($AcReceipt))
        {
            foreach($AcReceipt as $rows)
            {
                foreach($rows->accountReceiptReceivedAmount as $row){
                    $receivedAmount+=$row->amount;
                }
            }
        }

        $discountPriceAmount =$discountPrice->price??0;
        $data=['totalBilling'     => $finalTotal>0?(round($finalTotal-$discountPriceAmount-$totalReturn)):0,
                'receivedAmount'  => round($receivedAmount)??0,
                'discountAmount'  => $discountPriceAmount??0,
                'roundOffAmount'  => isset($roundOffPrice->price)&&$roundOffPrice->price?sprintf('%0.2f',$roundOffPrice->price):0,
                'dueAmount'       => round($finalTotal-$receivedAmount-$discountPriceAmount-$totalReturn)
            ];
        return  $data;
    }

    if (!function_exists('page_record_limit')) {
        function page_record_limit($type = null)
        {
            $values = [
                '20',
                '40',
                '60',
                '80',
                '100',
                '120',
                '140',
            ];

            return isset($type) && $type <= 8 && $type >= 1 ? $values[$type] : $values;
        }
    }

    if (!function_exists('stockOut')) {
        function stockOut($voucher_id,$voucher_type,$product_id,$pack_qty_out,$taxable_unit_price,$invoice_batch_id,$product_price_batch_id,$stockType='')
        {
            if($pack_qty_out>0)
            {

                $products        = Product::find($product_id);
                $productLocation = ProductLocation::select('location_rack_id')->where(['product_id'=>$product_id])->first();

                if($stockType=='')
                {
                    $stockType = $voucher_type;
                }else{
                    $stockType = $stockType;
                }
                $loginFinancialyear = \Session::get('user_financial_year_id') ?? '';
                $exitingStock       = Stock::where(
                    ['voucher_id'       => $voucher_id,
                    'voucher_type'      => $voucher_type,
                    'product_id'        => $product_id,
                    'batch_id'          => $product_price_batch_id,
                    'invoice_batch_id'  => $invoice_batch_id,
                    'stock_type'        => $stockType
                    ]
                    )->first();
                    if(isset($exitingStock)){
                        $exitingStock->update(
                            ['pack_qty_out'      => $pack_qty_out,
                            'taxable_unit_price' => $taxable_unit_price,
                            'batch_id'           => $product_price_batch_id,
                            'updated_by_user_id' => \Auth::id() ?? '',
                            'rack_location_id'   => $productLocation->location_rack_id??'',
                            'warehouse_id'       => $products->warehouse_id??'']
                        ); 
                    }else{
                        Stock::create(
                            ['voucher_id'       => $voucher_id??'',
                            'voucher_type'      => $voucher_type??'',
                            'product_id'        => $product_id,
                            'pack_qty_out'      => $pack_qty_out,
                            'taxable_unit_price'=> $taxable_unit_price,
                            'batch_id'          => $product_price_batch_id??'',
                            'created_by_user_id'=> \Auth::id() ?? '',
                            'company_id'        => \Auth::user()->company_id ?? '',
                            'financial_year_id' => $loginFinancialyear,
                            'status'            => 1,
                            'entry_date'        => date('Y-m-d H:i:s'),
                            'invoice_batch_id'  => $invoice_batch_id??'',
                            'stock_type'        => $stockType,
                            'rack_location_id'  => $productLocation->location_rack_id??'',
                            'warehouse_id'      => $products->warehouse_id??''
                        ]);
                    }
            }
            
           
        }
    }

    if(!function_exists('allActiveUsers')){
        function allActiveUsers(){
            return User::where('company_id',Auth::user()->company_id)
                 ->where('is_super_admin','0')
                 ->where('status',1)
                 ->orderBy('name','asc')
                 ->get(['id','name','email']);
        }
    }

    if(!function_exists('allCompanies')){
        function allCompanies(){
            $companies = Company::get(['id','name','is_default']);
            return $companies;
        }
    }
    if(!function_exists('allPaymentAccountingGroups')){
        function allPaymentAccountingGroups(){
            $accounting_group = Account::with('chart_of_account_sub_type')
            ->where(function ($query) {
                $query->whereHas('chart_of_account_sub_type', function ($accounting_group) {
                    $accounting_group->where('is_payment_mode', '1');
                });
            })
            ->get();
            return $accounting_group;
        }
    }

    if(!function_exists('allVoucherTypes')){
        function allVoucherTypes(){
            $voucher_types = VoucherType::where('status','1')->get(['name','code']);
            return $voucher_types;
        }
    }

    if(!function_exists('getTotalReceiptAmount')){
        function getTotalReceiptAmount($ac_receipt_details_ids = ''){
            $ids = explode(',', $ac_receipt_details_ids);

            if (empty($ids)) {
                return 0;
            }

            $total_amount = \DB::table('ac_receipt_details')
                ->select(\DB::raw('SUM(amount) as total_amount'))
                ->whereIn('ac_receipt_details.id', $ids)
                ->first();

            return $total_amount->total_amount;
        }
    }


    if (!function_exists('stockIn')) {
        function stockIn($product_id,$pack_qty_in,$taxable_unit_price,$invoice_batch_id,$product_price_batch_id,$stockType='',$voucher_id='',$voucher_type='',$free_qty='')
        {
            $products = Product::find($product_id);
            $productLocation = ProductLocation::select('location_rack_id')->where(['product_id'=>$product_id])->first();
            $loginFinancialYear = \Session::get('user_financial_year_id') ?? '';
            if($pack_qty_in>0)
            {
                if($stockType==''){
                    $stockType = $voucher_type;
                }else
                {
                    $stockType =  $stockType;
                }
            $exitingStock = Stock::where(
                ['voucher_id'       => $voucher_id,
                'voucher_type'      => $voucher_type,
                'product_id'        => $product_id,
                'batch_id'          => $product_price_batch_id,
                'invoice_batch_id'  => $invoice_batch_id,
                'stock_type'        => $stockType]
                )->first();
                if(isset($exitingStock)){
                    $exitingStock->update(
                        ['pack_qty_in'       => $pack_qty_in,
                        'taxable_unit_price' => $taxable_unit_price,
                        'batch_id'           => $product_price_batch_id,
                        'updated_by_user_id' => \Auth::id() ?? '',
                        'warehouse_id'       => $products->warehouse_id??'',
                        'rack_location_id'   => $productLocation->location_rack_id??'',
                        'free_qty'           => $free_qty??0,
                        ]
                       ); 
                }else{
                    Stock::create(
                        ['voucher_id'       => $voucher_id,
                        'voucher_type'      => $voucher_type,
                        'product_id'        => $product_id,
                        'pack_qty_in'       => $pack_qty_in,
                        'taxable_unit_price'=> $taxable_unit_price,
                        'batch_id'          => $product_price_batch_id,
                        'created_by_user_id'=> \Auth::id() ?? '',
                        'company_id'        => \Auth::user()->company_id ?? '',
                        'financial_year_id' => $loginFinancialYear,
                        'status'            => 1,
                        'entry_date'        => date('Y-m-d H:i:s'),
                        'invoice_batch_id'  => $invoice_batch_id,
                        'stock_type'        => $stockType,
                        'warehouse_id'      => $products->warehouse_id??'',
                        'rack_location_id'  => $productLocation->location_rack_id??'',
                        'free_qty'           => $free_qty??0,
                    ]);
                }
            }
            
           
        }
    }



    function ReturnTransactionCalculationReceiveAmount($invoice_id,$module_code)
    {
        
       
        $finalTotal    = SaleReturnDetails::where('sale_return_invoice_id',$invoice_id)->sum('total_amount','price');
        
        $discountPrice = SaleOthersTransaction::select('price')->where(['sale_invoice_id'=>$invoice_id,'account_id'=>67,'voucher_type'=>'SALE_RETURN'])->first();
        $roundOffPrice = SaleOthersTransaction::select('price')->where(['sale_invoice_id'=>$invoice_id,'account_id'=>110,'voucher_type'=>'SALE_RETURN'])->first();
        $receivedAmount=0;

        $discountPriceAmount =$discountPrice->price??0;
        $data=['totalBilling'     => $finalTotal>0?(round($finalTotal-$discountPriceAmount)):0,
                'receivedAmount'  => $receivedAmount??0,
                'discountAmount'  => $discountPriceAmount??0,
                'roundOffAmount'  => isset($roundOffPrice->price)&&$roundOffPrice->price?sprintf('%0.2f',$roundOffPrice->price):0,
                'dueAmount'       => round($finalTotal-$receivedAmount-$discountPriceAmount)
            ];
        return  $data;
    }

    function PurchaseTransactionCalculationReceiveAmount($invoice_id,$module_code)
    {
        
       
        $paymentVoucher = PaymentVoucher::select(['id', 'voucher_id'])
        ->with(['accountReceiptReceivedAmount'])
        ->where(['module_code' => $module_code, 'voucher_id' => $invoice_id])
        ->get();


        $finalTotal    = PurchaseInvoiceDetails::where('purchase_invoice_id',$invoice_id)->sum('total_amount','price');
        $discountPrice = PurchaseOthersTransaction::select('price')->where(['purchase_invoice_id'=>$invoice_id,'account_id'=>67,'voucher_type'=>'PURCHASE'])->first();
        $roundOffPrice = PurchaseOthersTransaction::select('price')->where(['purchase_invoice_id'=>$invoice_id,'account_id'=>110,'voucher_type'=>'PURCHASE'])->first();

        $receivedAmount=0;
        if(isset($paymentVoucher))
        {
            foreach($paymentVoucher as $rows)
            {
                foreach($rows->accountReceiptReceivedAmount as $row){
                    $receivedAmount+=$row->amount;
                }
            }
        }

        $discountPriceAmount =$discountPrice->price??0;
        $data=['totalBilling'     => $finalTotal>0?(round($finalTotal-$discountPriceAmount)):0,
                'receivedAmount'  => round($receivedAmount)??0,
                'discountAmount'  => $discountPriceAmount??0,
                'roundOffAmount'  => isset($roundOffPrice->price)&&$roundOffPrice->price?sprintf('%0.2f',$roundOffPrice->price):0,
                'dueAmount'       => round($finalTotal-$receivedAmount-$discountPriceAmount)
            ];
        return  $data;
    }

    if (!function_exists('OwnershipTypes')) {
        function OwnershipTypes($type = null)
        {
            $values = [
                '1'  => 'Owned',
                '2'  => 'Contractual',
            ];

            return isset($type) && $type <= 8 && $type >= 1 ? $values[$type] : $values;
        }
    }

    if (!function_exists('calculateInclusive')) {
        function calculateInclusive($priceWithTax, $taxRate) {
            $basePrice = $priceWithTax / (1 + $taxRate);
            $taxAmount = $priceWithTax - $basePrice;
            
            return [
                'basePrice' => round($basePrice, 2),
                'taxAmount' => round($taxAmount, 2)
            ];
        }
    }
    if (!function_exists('calculateExclusive')) {
        function calculateExclusive($basePrice, $taxRate) {
            $taxAmount    = $basePrice * $taxRate;
            $priceWithTax = $basePrice + $taxAmount;
            
            return [
                'taxAmount'    => round($taxAmount, 2),
                'priceWithTax' => round($priceWithTax, 2)
            ];
        }
    }
    if (!function_exists('billingRangeFlag')) {
        function billingRangeFlag($high_value, $low_value, $result) {
            if ((float)$result < (float)$low_value) {
                return 'low ' . $high_value .' '.$low_value .' '. $result;
            } else if ($result > $high_value) {
                return 'high';
            } else {
                return '';
            }
        }
    }
    if (!function_exists('receivedAmount')) {
        function receivedAmount($ac_receipt_id) {
            if (empty($ac_receipt_id)) {
                return 0;
            }

            $data = AcReceiptDetail::select(
                    \DB::raw('SUM(ac_receipt_details.amount) as ac_receipt_amount')
                )
                ->where('ac_receipt_details.ac_receipt_id',$ac_receipt_id)
                ->first();

            return $data->ac_receipt_amount ?? 0;
        }
    }

    if (!function_exists('getCurrentStock')) {
        function getCurrentStock($productId,$priceId='') {
            $productId = $productId;
            $priceId   = $priceId;
            $stockData = Stock::select([
                \DB::raw("SUM(pack_qty_in) AS stock_in_count"),
                \DB::raw("SUM(pack_qty_out) AS stock_out_count"),
                \DB::raw("SUM(free_qty) AS free_qty_count")
                ])
            ->where('product_id', $productId);
            if(isset($priceId) && $priceId!='')
            {
                $stockData =  $stockData->where('batch_id',$priceId);
            }
            
            $stockData=$stockData->groupBy('product_id')
            ->first();

            if (!$stockData) {
                return 0;
            }

            $current_stock=isset($stockData->stock_in_count) && $stockData->stock_in_count!='' ? (($stockData->stock_in_count-$stockData->stock_out_count)>0?$stockData->stock_in_count-$stockData->stock_out_count:0):0;
            return ($current_stock + $stockData->free_qty_count);
        }
    }


    if (!function_exists('getProductStock')) {
        function getProductStock($productId) {
            $productId = $productId;
            $stockData = Stock::select([
                \DB::raw("SUM(pack_qty_in) AS stock_in_count"),
                \DB::raw("SUM(pack_qty_out) AS stock_out_count"),
                \DB::raw("SUM(free_qty) AS free_qty_count"),
                ])
            ->where('product_id', $productId);
            $stockData=$stockData->groupBy('product_id')
            ->first();

            $current_stock=isset($stockData->stock_in_count) && $stockData->stock_in_count!='' ? 
                                (($stockData->stock_in_count-$stockData->stock_out_count)?$stockData->stock_in_count-$stockData->stock_out_count:0):0;

            $data['stock_in']  = $stockData->stock_in_count + $stockData->free_qty_count;
            $data['stock_out'] = $stockData->stock_out_count;
            $data['current_stock'] = $current_stock + $stockData->free_qty_count;
            
            return $data;
        }
    }

    if(!function_exists('getAccountState')){
        function getAccountState($account_id) {
            $accountAddress = AccountAddress::with('state')->select('state_id')->where('account_id',$account_id)->first();
            return $accountAddress->state->name??'';
        }
    }

    if(!function_exists('countStudyMaterials')){
        function countStudyMaterials($course_id,$materialTypeId){
            $studyMaterials = StudyMaterial::select('id')->where(['course_id'=>$course_id,'material_type_id'=>$materialTypeId])->get();
            return count($studyMaterials);
        }
    }

    if (!function_exists('taskStatus')) {
        function taskStatus($status = null)
        {
            $values = [
                '1'  => 'Pending',
                '2'  => 'Processing',
                '3'  => 'Hold',
                '4'  => 'Cancel',
                '5'  => 'Done',
            ];

            return isset($status) && $status <= 8 && $status >= 1 ? $values[$status] : $values;
        }
    }

    if(!function_exists('countPublicContent')){
        function countPublicContent($categoryId,$subCategoryId){
            $publicContent = PublicContent::select('id')->where(['public_content_category_id'=>$categoryId,'sub_category_id'=>$subCategoryId])->get();
            return count($publicContent);
        }
    }


?>
