<?php

use Carbon\Carbon;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use App\Models\Stock\GenerateCodes;
use Illuminate\Support\Facades\Log;
use App\Models\Stock\StockinHistory;
use Illuminate\Support\Facades\Storage;

define( 'MINUTE_IN_SECONDS', 60 );
define( 'HOUR_IN_SECONDS', 60 * MINUTE_IN_SECONDS );
define( 'DAY_IN_SECONDS', 24 * HOUR_IN_SECONDS );
define( 'WEEK_IN_SECONDS', 7 * DAY_IN_SECONDS );
define( 'MONTH_IN_SECONDS', 30 * DAY_IN_SECONDS );
define( 'YEAR_IN_SECONDS', 365 * DAY_IN_SECONDS );


function generateReference($length) {
    $reference = implode('', [
        bin2hex(random_bytes(2)),
        bin2hex(random_bytes(2)),
        bin2hex(chr((ord(random_bytes(1)) & 0x0F) | 0x40)) . bin2hex(random_bytes(1)),
        bin2hex(chr((ord(random_bytes(1)) & 0x3F) | 0x80)) . bin2hex(random_bytes(1)),
        bin2hex(random_bytes(2))
    ]);

    return strtoupper(strlen($reference) > $length ? substr($reference, 0, $length) : $reference);
}

function generateRowCode($len = 8){
    return strtoupper(substr(base_convert(uniqid(mt_rand()), 16, 36), 0, $len));
}

function getMonthDays($month = NULL, $year = NULL)
{
    if(is_null($month)) $month = date('m');
    if(is_null($year)) $year = date('Y');
    $startDate = "01-" . $month . "-" . $year;
    $startTime = strtotime($startDate);
    $endTime = strtotime("+1 month", $startTime);
    for($i=$startTime; $i < $endTime; $i+=86400){
        $list[] = date('Y-m-d', $i);
    }
    return $list;
}

function getNotifiableUsers($user)
{
    return User::where('company_id', $user->company_id)
                 ->where('id', '!=', $user->id)
                 ->get();
}


function setEnvironment(array $items)
{
    $str = file_get_contents(base_path('.env'));

    if (count($items) > 0) {
        foreach ($items as $item) {
            $key = strtoupper($item->key);
            $str .= "\n"; // In case the searched variable is in the last line without \n
            $keyPosition = strpos($str, "{$key}=");
            $endOfLinePosition = strpos($str, "\n", $keyPosition);
            $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition);

            // If key does not exist, add it
            if (!$keyPosition || !$endOfLinePosition || !$oldLine) {
                $str .= "{$key}='{$item->value}'\n";
            } else {
                $str = str_replace($oldLine, "{$key}='{$item->value}'", $str);
            }
        }
    }

    $str = substr($str, 0, -1);
    if (!file_put_contents(base_path('.env'), $str)) return false;
    return true;
}

function handleConsumedItems(int $itemId, int $quantity)
{
    if ($quantity > 0) {
        $row = StockinHistory::where('product_id', $itemId)->whereNotIn('status', ['EXPIRED','CONSUMED'])->first();
        if ($row->quantity > ($row->consumed_qty + $quantity)) {
            $row->consumed_qty += $quantity;
            $row->save();
        } else {
            $remain = $row->quantity - $row->consumed_qty;
            $row->consumed_qty = $row->quantity;
            $row->status = 'CONSUMED';
            $row->save();
            $quantity -= $remain;
            if ($quantity > 0) {
                return handleConsumedItems($itemId, $quantity);
            }
        }
    } else {
        $row = StockinHistory::where('product_id', $itemId)
                                ->whereIn('status', ['IN_STOCK', 'CONSUMED'])
                                ->where('consumed_qty', '>', 0)
                                ->orderBy('id', 'DESC')
                                ->first();
        // Here will a + (-b) = a - b
        $quantity = $row->consumed_qty + $quantity;
        if ($quantity <= 0) {
            $row->consumed_qty = 0;
            $row->status = 'IN_STOCK';
            $row->save();
            if ($quantity != 0) {
                return handleConsumedItems($itemId, $quantity);
            }
        } else {
            $row->consumed_qty -= $quantity;
            $row->status = 'IN_STOCK';
            $row->save();
        }
    }
}

function formatSN($num)
{
    if($num < 10)
    {
        return "0".$num;
    }else
    {
        return $num;
    }
    return null;
}

function createTransactCode($TYPE)
{
    $ORG = "NIY";
    $TYPE = strtoupper($TYPE);

    $TRANSACTCODE = GenerateCodes::select('id', 'sn_type','sn_m','sn_id_y','sn_id_l','sn_id_n')
                            ->where('sn_type',$TYPE)
                            ->first();
    
    if($TRANSACTCODE){
        $month  =    $TRANSACTCODE->sn_m;
        $year   =    $TRANSACTCODE->sn_id_y;
        $letter =    $TRANSACTCODE->sn_id_l;
        $num    =    $TRANSACTCODE->sn_id_n;
    }else{
        return;
    }

    $num++;
    if($num > 999)
    {
        $letter++;
        $num = 1;
    }

    $n_month = date('m');
    if($n_month > $month){
        $month = $n_month;
    }
    
    $n_year = (int) date('Y') - 2000;
    if($n_year > $year)
    {
        $year = $n_year;
        $letter = 'A';
        $num = 1;
    }

    $TRANSACTCODE->sn_m = $month;
    $TRANSACTCODE->sn_id_y = $year;
    $TRANSACTCODE->sn_id_l = $letter;
    $TRANSACTCODE->sn_id_n = $num;
    $TRANSACTCODE->save();
    return $ORG .'-'. $TYPE . formatSN($year). $month . $letter. formatSN($num);
}

function createProductCode($CATEGO, $NAME, $TYPE="PRO")
{
    $ORG = "NIY";
    $TYPE = strtoupper($TYPE);

    $PRODUCTCODE = GenerateCodes::select('id', 'sn_type','sn_id_l','sn_id_n')
                            ->where('sn_type',$TYPE)
                            ->first();
    
    if($PRODUCTCODE){
        $letter =    $PRODUCTCODE->sn_id_l;
        $num    =    $PRODUCTCODE->sn_id_n;
    }else{
        return;
    }

    $num++;
    if($num > 999)
    {
        $letter++;
        $num = 1;
    }

    $PRODUCTCODE->sn_id_l = $letter;
    $PRODUCTCODE->sn_id_n = $num;
    $PRODUCTCODE->save();

    $nameWithoutSpaces = str_replace(' ', '', $NAME);
    $categoryWithoutSpaces = str_replace(' ', '', $CATEGO);
    $NAMECHAR = strtoupper(substr($nameWithoutSpaces, 0, 4));
    if (strlen($NAMECHAR) < 3) {
        $NAMECHAR = strtoupper($nameWithoutSpaces);
    }
    $CATEGOCHAR = strtoupper(substr($categoryWithoutSpaces, 0, 1));

    return $CATEGOCHAR .'-'. $NAMECHAR . $letter. formatSN($num);
}


function showTransactCode($TYPE)
{
    $ORG = "MAM";
    $TYPE = strtoupper($TYPE);

    $TRANSACTCODE = GenerateCodes::select('sn_type','sn_m','sn_id_y','sn_id_l','sn_id_n')
                                    ->where('sn_type',$TYPE)
                                    ->first();

    if($TRANSACTCODE){
            $month  =    $TRANSACTCODE->sn_m;
            $year   =    $TRANSACTCODE->sn_id_y;
            $letter =    $TRANSACTCODE->sn_id_l;
            $num    =    $TRANSACTCODE->sn_id_n;
    }else{
        return;
    }
      
    $num++;
    if($num > 999)
    {
        $letter++;
        $num = 1;
    }

    $n_month = date('m');
    if($n_month > $month){
        $month = $n_month;
    }

    $n_year = (int) date('Y') - 2000;
    if($n_year > $year)
    {
        $year = $n_year;
        $letter = 'A';
        $num = 1;
    }
    
    return $ORG .'-'. $TYPE . formatSN($year). $month . $letter. formatSN($num);
}