<?php

namespace App\Http\Livewire\Pages\Patch;

use Livewire\Component;
use App\Models\ConfFormatFile;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Livewire\WithFileUploads;

use Illuminate\Http\UploadedFile;
use Facades\Livewire\GenerateSignedUploadUrl;
use Illuminate\Validation\ValidationException;
use Livewire\Exceptions\S3DoesntSupportMultipleFileUploads;
use Livewire\FileUploadConfiguration;

use Illuminate\Support\Facades\Storage;
use Livewire\TemporaryUploadedFile;
use App\Traits\CustomTemporaryFileUpload;
class PatchMasterFile extends Component
{
    use WithFileUploads;
    use CustomTemporaryFileUpload;
    public $file, $format_file_id, $messages, $formatFile, $limit, $noLimit, $genPatch, $createPatch  = false, $sendToEec = false, $genWithSmartUpdate = false;
    protected $formatFiles;

    protected $rules = [
        'name' => 'required|string|max:255',
        'files.*' => 'required|file|max:12209752',
    ];

    public function createPatch()
    {

        $fileData = $this->file->getRealPath();
      
        $fileFormat = ConfFormatFile::where('formatservice_ID', $this->format_file_id)->first();
        $jsonFilePath = storage_path(str_replace(".inc", ".json",  $fileFormat->file));


        if (!file_exists($jsonFilePath)) {
            session()->flash('error', 'Format JSON file not found.');
            return;
        }
        $formatData = json_decode(file_get_contents($jsonFilePath), true);

        $message = '';
        if ($this->createPatch) {
            $sqlPackAll = $this->readTxt($fileData, $formatData, $fileFormat, $this->limit, $this->noLimit);
            $this->processPatches($sqlPackAll, $fileFormat, $this->genWithSmartUpdate);
            $message .=  'Patch master file created successfully.';
        }


        $timeStampEec = Carbon::now()->toDateString();
        $datetime = Carbon::now()->toDateTimeString();
        $typeEec = $fileFormat->ac ?? '';

        if ($this->sendToEec && $typeEec !== '') {
            $uid = auth()->user()->id;
            $response = $this->sendMasterFileToEcc(config('services.eec.url'), [
                'type' => $typeEec,
                'file' => fopen($fileData, 'r'),
                'timestamp' => $timeStampEec,
            ]);

            $reponseStatus = $response->status();
            $responseDate = $response->json();
            $requestData = json_encode([
                'type' => $typeEec,
                'file' => $fileData,
                'timestamp' => $timeStampEec,
            ]);

            $this->keepTransactionToEcc($uid, $typeEec, basename($fileData), $requestData, $datetime, $reponseStatus, json_encode($responseDate));
            $message .=  'Send EEC successfully.';
            // if ($RESPSTATUS == 200) {
            //     return response()->json(['message' => 'Send MasterFile To EEC'], 200);
            // } else {
            //     return response()->json(['message' => 'Can Not Send MasterFile To EEC'], 500);
            // }
        } else {
            // return response()->json(['message' => 'MasterFile Not config to EEC'], 400);
        }

        return redirect()->route('patch.index')->with('message', $message);
    }
    private function sendMasterFileToEcc($url, $postData)
    {

        return Http::attach('file', $postData['file'])
            ->asMultipart()
            ->post($url, [
                'type' => $postData['type'],
                'timestamp' => $postData['timestamp'],
            ]);
    }

    private function keepTransactionToEcc($UID, $TYPE, $FILENAME, $REQDATA, $ACTDATETIME, $RESPSTATUS, $RESPDATA)
    {
        DB::table('log_send_master2eec')->insert([
            'UID' => $UID,
            'TYPE' => $TYPE,
            'FILENAME' => $FILENAME,
            'REQDATA' => $REQDATA,
            'ACTDATETIME' => $ACTDATETIME,
            'RESPSTATUS' => $RESPSTATUS,
            'RESPDATA' => $RESPDATA,
        ]);
    }

    function processPatches($sqlPackAll,  $fileFormat, $genSpnSmartUpdateDecode)
    {
        $uid = auth()->user()->id;
        $pLevel = "Critical";
        $nameFormat = $fileFormat->name ?? 'Unknown Format';
        $pDesc = $nameFormat;
        $day = Date('j');
        $month = Date('n');
        $year = Date('Y');
        $pApproveDate = date("Y-m-d h:i:s");
        $partPatch = '';
        $countSql = count($sqlPackAll);
        $part = 1;

        foreach ($sqlPackAll as $i__ => $sqlPack) {
            if ($countSql != 1 && !$this->noLimit) {
                $partPatch = 'Part ' . $part++;
            }
            $tis620_encoded = iconv('UTF-8', 'TIS-620', var_export($sqlPack, true));
            $ALL64 = base64_encode(gzcompress($tis620_encoded));
    
        
            $patchCode = '$ALL64="' . $ALL64 . '";' . "\n";

            if ($genSpnSmartUpdateDecode) {
                $updatedecode = '$ALLVAR=gzuncompress(spnsmartupdatedecode($ALL64));' . "\n";
            } else {
                $updatedecode = '$ALLVAR=gzuncompress(base64_decode($ALL64));' . "\n";
            }

            $patchCode .= $updatedecode;
            $patchCode .= "eval('\$SQL='.".'$ALLVAR.";");'."\n";
            $patchCode .= $this->generatePatchCode($countSql , $i__);

            if ($this->noLimit && ($i__ == $countSql - 1)) {
                $this->savePatch($patchCode, $nameFormat, $day, $month, $year, $partPatch, $pLevel, $pDesc, $uid, $pApproveDate);
            } elseif (!$this->noLimit) {
                $this->savePatch($patchCode, $nameFormat, $day, $month, $year, $partPatch, $pLevel, $pDesc, $uid, $pApproveDate);
            }
        }
    }
    private function generatePatchCode($countSql , $i__)
    {
        $patchCode = '';
        $patchCode .= '$insert=$SQL["insert"];' . "\n";
        $patchCode .= '$update=$SQL["update"];' . "\n";
        $patchCode .= '$select=$SQL["select"];' . "\n";
        $patchCode .= '$select2=$SQL["select2"];' . "\n";
        $patchCode .= '$DATABASE=$SQL["DATABASE"];' . "\n";
        $patchCode .= '$CountSQL_=count($insert);' . "\n";
        $patchCode .= '$succ="0";' . "\n";
        $patchCode .= '$succ2="0";' . "\n";
        $patchCode .= 'for($i_=0;$i_<$CountSQL_;$i_++){' . "\n";
        $patchCode .= '    $INSERT_ID="";' . "\n";
        $patchCode .= '    if($DBTYPE=="MYSQL"){' . "\n";
        $patchCode .= '        $sql=$insert[$i_]." ON DUPLICATE KEY UPDATE ".$update[$i_];' . "\n";
        $patchCode .= '    }' . "\n";
        $patchCode .= '    if($DBTYPE=="MSSQL"){' . "\n";
        $patchCode .= '        $sql="IF EXISTS (".$select[$i_].") BEGIN UPDATE $DATABASE SET ".$update[$i_].$select2[$i_]." END ELSE ".$insert[$i_];' . "\n";
        $patchCode .= '    }' . "\n";
        $patchCode .= '    exec_query($sql);' . "\n";
        $patchCode .= '    $succ++;' . "\n";
        $patchCode .= '    if($INSERT_ID!=""){$succ2++;}' . "\n";
        $patchCode .= '}' . "\n";
        $patchCode .= 'unset($ALL64);' . "\n";
        $patchCode .= 'unset($ALLVAR);' . "\n";
        $patchCode .= 'unset($SQL);' . "\n";
        $patchCode .= 'unset($insert);' . "\n";
        $patchCode .= 'unset($update);' . "\n";
        $patchCode .= 'unset($select);' . "\n";
        $patchCode .= 'unset($select2);' . "\n";
        $patchCode .= '$PRINT_ .=  date("h:i:s")." Process '.($i__+1).' / ' . $countSql . ' Successful Update $succ data(s) (Added = $succ2) from $CountSQL_.</br>";' . "\n";

        return $patchCode;
    }

    private function savePatch($patchCode, $nameformat, $day, $month, $year, $partPatch, $PLEVEL, $PDESC, $UID, $PAPPROVEDATE)
    {
        $patchCode .= '$PRINTOUT=$PRINT_;' . "\n";
        $patchCode .= '$PATCH_STATUS="OK";' . "\n";
        // $patchCode = str_replace("'", "''", $patchCode);

        $data = [
            'PATCHNAME' => "Update Master File $nameformat วันที่ $day เดือน $month ปี $year $partPatch",
            'PDATE' => Carbon::now(),
            'PLEVEL' => $PLEVEL,
            'PCODE' => 'SHIPPINGNET',
            'MAJOR_VERSION' => 'ALL',
            'PDESC' => $PDESC,
            'POWNER' => $UID,
            'PTYPE' => 'UPDATE MASTER',
            'PAPPROVEDATE' => $PAPPROVEDATE,
            'PATCHCODE' => iconv("utf-8", "tis-620" ,$patchCode),
            'UNINSTALL' => '$DONE=1;',
            'PATCHCODE_SERVER' => '$DONE=1;',
        ];

        DB::table('conf_smartupdate')->insert($data);
    }
    private function readTxt($filePath, $formatData, $ac, $limit = 10000, $noLimit = false)
    {
        $sqlPackAll = [];
        $count = 0;
        $fileHandle = fopen($filePath, "r");

        while (!feof($fileHandle)) {
            $text = fgets($fileHandle);
            $text = iconv('TIS-620', 'UTF-8', $text);

            $X = $Y = $Z = 0;

          

            $primaryKeyConditions = [];

            foreach ($formatData['primary_key'] as $keyIndex => $primaryKey) {
                $fieldFormat = $formatData['format'][$keyIndex];
                $type = $fieldFormat['TYPE'];

                if (strpos($type, 'DE') !== false) {
                    $type = str_replace('DE', '', $type);

                    $type = (int) $type + 1;
                }

                $type = (int) filter_var($type, FILTER_SANITIZE_NUMBER_INT);
                $fieldValue = mb_substr($text, $Y, $type, 'UTF-8');
                $Y += $type;

                if ($fieldFormat['FORMAT'] === 'date') {
                    $fieldValue = $this->convertDate($fieldValue);
                }

                $primaryKeyConditions[] = $primaryKey['FILD'] . " = '" . trim($fieldValue) . "'";
            }

            $select2[] = " WHERE ".implode(' AND ', $primaryKeyConditions);
            $select[] = "SELECT * FROM " . $formatData['database'] . " ". " WHERE ".implode(' AND ', $primaryKeyConditions);

        
            $insertFields = [];
            $insertValues = [];

            foreach ($formatData['format'] as $fieldFormat) {
                $type = $fieldFormat['TYPE'];

                if (strpos($type, 'DE') !== false) {
                    $type = str_replace('DE', '', $type);
                    $type = (int) $type + 1;
                }
                $type = (int) filter_var($type, FILTER_SANITIZE_NUMBER_INT);
            
                $fieldValue = mb_substr($text, $X, $type, 'UTF-8');

                $X += $type;
                if ($fieldFormat['FORMAT'] === 'date') {
                    $fieldValue = $this->convertDate($fieldValue);
                }
       
                $insertFields[] = "`" . $fieldFormat['FILD'] . "`";
                $insertValues[] = "'" . str_replace("'", "''", trim($fieldValue)) . "'";
            }

            $insert[] = "INSERT INTO " . $formatData['database'] . " (". implode(',', $insertFields) . ") VALUES (" . implode(',', $insertValues) . ")";

            $update[] = $this->generateUpdateQuery($formatData['format'], $text, $Z, $formatData['primary_key']);

            $sqlPack = [
                'insert' => $insert,
                'update' => $update,
                'select' => $select,
                'select2' => $select2,
                'DATABASE' => $formatData['database'],
                'counter' => $count+=1
            ];

            $sqlPackAll[] = $sqlPack;

            if ($this->noLimit && $this->limit > 10000) {
                break;
            } elseif ($this->limit >= $limit) {
                break;
            }
        }

        fclose($fileHandle);

        return $sqlPackAll;
    }

    private function convertDate($datetime)
    {
        $year = substr($datetime, 4, 8) - 543;
        $month = substr($datetime, 2, 2);
        $day = substr($datetime, 0, 2);
        return date("Y-m-d", mktime(0, 0, 0, $month, $day, $year));
    }

    private function generateUpdateQuery($formatData, $text, &$Z, $primaryKeys)
    {
        $update = "";

        foreach ($formatData as $index => $fieldFormat) {
            $type = $fieldFormat['TYPE'];

            if (strpos($type, 'DE') !== false) {
                $type = str_replace('DE', '', $type);
                $type = (int) $type + 1;
            }
            $type = (int) filter_var($type, FILTER_SANITIZE_NUMBER_INT);
            $fieldValue = mb_substr($text, $Z, $type, 'UTF-8');
            $Z += $type;

            if ($fieldFormat['FORMAT'] === 'date') {
                $fieldValue = $this->convertDate($fieldValue);
            }

            if (!in_array($fieldFormat['FILD'], array_column($primaryKeys, 'FILD'))) {
                if ($update != "") {
                    $update .= ", ";
                }

                $update .= "`" . $fieldFormat['FILD'] . "` = '" . str_replace("'", "''", trim($fieldValue)) . "'";
            }
        }

        return $update;
    }

    public function render()
    {
        $this->formatFiles = ConfFormatFile::all();
        return view('livewire.pages.patch.patch-master-file', with([
            'formatFiles' => $this->formatFiles
        ]));
    }
}
