<?php

namespace App\Http\Livewire\Pages\ManualResponse;

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use App\Http\Controllers\ManualResponse\GenXmlController;
use App\Http\Controllers\ManualResponse\SpnConfigController;
use App\Models\ConfListProfile;
use App\Models\ManualResponse\MasterMessages;
use App\Models\ManualResponse\MasterResponseTemplates;
use App\Models\ManualResponse\MasterDocTypes;
use App\Models\ManualResponse\TabManualResponseLog;
use App\Models\ManualResponse\UsersConnectSpn;
use App\Models\MasterResponseMessageType;
use Carbon\Carbon;
use CURLFile;

class ManualResponse extends Component
{
    public $displayCustomizeDiv = false;
    public $masterMsg ,  $showSearch;
    public $messageTypes = [];
    public $messageId;
    public $responseTemplates = [];
    public $templateId;

    public $templateList;

    public $docTypes = [];
    public $docType;

    public $xmlContent;
    public $xmlData = [];
    public $xmlWithData = [];

    public $activeLoader = false;
    public $changeBtnColor;

    public $lockData;
    public $disableLockData = true;
    public $structureXML;

    public $disableDocType = false;

    protected $rules = [
        'messageId' => 'required|string',
        'templateId' => 'required|string'
    ];

    protected $messages = [
        'messageId.required' => '*Message cannot be empty.',
        'templateId.required' => '*Template cannot be empty.'
    ];

    protected $listNonLockData = [
        "MessageType",
        "AuditDateTime",
        "Message",
        "Status"
    ];

    public function mount()
    {
        $this->messageTypes = MasterMessages::pluck('value', 'id')->toArray();
        $this->docTypes = MasterDocTypes::pluck('name', 'code')->toArray();
        $this->changeBtnColor = "bg-[#A020F0] hover:bg-[#B34FEF] text-white font-bold";
        $this->lockData = false;
        $this->disableLockData = true;
    }

    public function render()
    {
        if ($this->messageId != '') {
            $this->responseTemplates = MasterResponseTemplates::where('mid', $this->messageId)->get()->mapWithKeys(function ($record) {
                $description = $record->description != '' ? ' ' . ' (' . $record->description . ')' : '';
                return [$record->id => $record->code . ': ' . $record->name . $description];
            })->toArray();
            $this->docTypes = MasterDocTypes::where('mid', $this->messageId)->pluck('name', 'code')->toArray();
        }

        return view('livewire.pages.manual-response.manual-response-index');
    }

    public function updatedMessageId()
    {
        $this->templateId = '';
        $this->responseTemplates = [];
        $this->docTypes = [];
        $this->docType = '';
        $this->xmlData = [];
        $this->xmlContent = '';
        $this->displayCustomizeDiv = false;
        if($this->messageId == 3 || $this->messageId == 4){
            $this->disableDocType = true;
        }else{
            $this->disableDocType = false;
        }
        $this->lockData = false;
    }

    public function updatedXmlTagInputList()
    {
        if ($this->xmlData === null) {
            $this->xmlContent = '';
        }
    }

    public function gotoCustomize()
    {
        $this->disableLockData = false;
        $tmp_xmlData = $this->xmlData;
        $this->xmlData = [];
        $this->xmlContent = '';
        $this->validate();

        //Default documentType in case messsage is export/import
        if(empty($this->docType)){
            if($this->messageId == 1){
                $this->docType = 1;
            }else if($this->messageId == 2){
                $this->docType = 0;
            }
        }

        $xmlGenerator = new GenXmlController();
        $xml = $xmlGenerator->generateXML($this->templateId, $this->docType, $this->lockData);
        if ($xml == null) {
            session()->flash('templateNotFound', 'Template is not found!');
        } else {
            $this->displayCustomizeDiv = true;
            $this->xmlContent = $xml['xmlContent'];
            $this->xmlData = $xml['xmlWithData'];

            //For response Export: 9904: Goods Transition Control Already Cancel Matching -> No auto-gen Declaration Number.
            $messageCode = MasterResponseTemplates::where('id', $this->templateId)->value('code') ?? '';
            if($messageCode == '9904'){
                $this->xmlData['DeclarationNumber'] = '';
            }

            if($this->lockData){
                foreach($this->xmlData as $key => $val){
                    if(isset($tmp_xmlData[$key]) && !in_array($key, $this->listNonLockData)){
                        $this->xmlData[$key] = $tmp_xmlData[$key];
                    }

                    if(isset($tmp_xmlData['ReferenceNumber']) && isset($this->xmlData['ReferenceNo'])){
                        $this->xmlData['ReferenceNo'] = $tmp_xmlData['ReferenceNumber'];
                    }
                }
            }
            
            $this->reGenerateXML();
        }

        $this->changeBtnColor = "bg-slate-150 font-medium text-slate-800 hover:bg-slate-200 focus:bg-slate-200 active:bg-slate-200/80 rounded-md border border-[#e5e7eb] ";
    }

    public function reGenerateXML()
    {
        $xmlGenerator = new GenXmlController();
        $xml = $xmlGenerator->updateXmlValues($this->xmlContent, $this->xmlData);
        $this->xmlContent = $xml;
    }

    public function mockUpXML()
    {
        $this->xmlData = $this->xmlWithData;
    }

    public function generateAndUploadXml()
    {
        $this->reGenerateXML();

        $validateResult = $this->validateBeforeSend();
        if(!$validateResult['success']){
            $this->dispatchBrowserEvent('open-modal', [
                'name' => 'alert-modal',
                'message' => $validateResult['message'],
                'status' => 'failed'
            ]);
            return;
        }

        // Generate XML file from string
        $now = Carbon::now();
        $filename = 'manual_response_' . $now->format('Ymd_His') . ".xml";
        Storage::disk('local')->put($filename, $this->xmlContent);
        $filePath = storage_path('app/' . $filename);

        $currentUser = Auth::user();
        $userConnect = UsersConnectSpn::where('uid', $currentUser->id)->first();
        if(!isset($userConnect)){
            $this->dispatchBrowserEvent('open-modal', [
                'name' => 'alert-modal',
                'message' => 'SPN config is not found!',
                'status' => 'failed'
            ]);
            return;
        }

        $spnConfigController = new SpnConfigController();
        $spnConfig = $spnConfigController->init_connection($userConnect);

        if($spnConfig != null && $spnConfig['success'] == 'true'){
            $uid = $spnConfig['uid'];
            $ucode = $spnConfig['ucode'];

            $ch = curl_init();

            $cfile = new CURLFile($filePath, 'application/xml', $filename);
            $postData = [
                'UID' => $uid,
                'UCODE' => $ucode,
                'SERVICENAME' => 'imcoreservice',
                'ACTION' => 'get_response_customs',
                'profilecode' => '',
                'API_PLACE_FILE' => 'Y',
                'file' => $cfile
            ];

            curl_setopt($ch, CURLOPT_URL, $userConnect->link . "/IE5DEV.shippingnet/data_defaulttemplate.php");
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            $result = curl_exec($ch);
            $error = curl_error($ch);
            curl_close($ch);

            $messageType = MasterMessages::where('id', $this->messageId)->value('name') ?? '';
            TabManualResponseLog::create([
                'uid' => $currentUser->id,
                'title' => 'Send Manual Response',
                'detail' => "Username: " . $userConnect->username . "\nLink: " . $userConnect->link,
                'message_type' => $messageType,
                'xml_content' => base64_encode($this->xmlContent),
                'reference_number' => $this->xmlData['ReferenceNumber'] ?? $this->xmlData['ReferenceNo'] ?? '',
                'declaration_number' => $this->xmlData['DeclarationNumber'] ?? $this->xmlData['DocumentNumber'] ?? '',
                'link' => $userConnect->link
            ]);

            if ($error) {
                //Cannot send response to SPN
                $alertMessage = $error;
                $alertStatus = 'failed';
            } elseif(!$this->validateAfterSend($result)) {
                $alertMessage = 'Unable to upload the file to SPN.<br>Please ensure the INBOX folder is properly set up before retrying.';
                $alertStatus = 'failed';
            } else {
                $alertMessage = 'Send response successfully';
                $alertStatus = 'success';
            }
            Storage::disk('local')->delete($filename);
        }else if($spnConfig != null && $spnConfig['success'] == 'false'){
            $alertMessage = $spnConfig['message'];
            $alertStatus = 'failed';
        }else{
            //Cannot get UID/UCODE from SPN
            $alertMessage = 'Cannot connect to SPN';
            $alertStatus = 'failed';
        }

        $this->dispatchBrowserEvent('open-modal', [
            'name' => 'alert-modal',
            'message' => $alertMessage,
            'status' => $alertStatus
        ]);
    }

    private function validateBeforeSend(){
        $messageType = $this->xmlData['MessageType'] ?? '';
        $referenceNo = $this->xmlData['ReferenceNumber'] ?? $this->xmlData['ReferenceNo'] ?? '';
        $declarationNo = $this->xmlData['DeclarationNumber'] ?? $this->xmlData['DocumentNumber'] ?? '';
        $profileProds = ConfListProfile::where('type', 'PROD')->pluck('name')->toArray();

        //Validate reference number format
        if (!preg_match('/^[A-Z]{4}[0-9]{9}$/', $referenceNo)) {
            return [
                "success" => false, 
                'message' => 'Reference Number is incorrect format.'
            ];
        }

        //Validate profile production
        if(in_array(substr($referenceNo, 0, 1), $profileProds)){
            return [
                "success" => false, 
                'message' => 'Profile production is not allowed.'
            ];
        }

        //Validate profile production
        if(in_array($messageType, ['XCDA', 'XCDR']) && $declarationNo == ''){
            return [
                "success" => false, 
                'message' => 'Cancel template is required "Declaration Number" field.'
            ];
        }

        return ['success' => true, 'message' => ''];
    }

    private function validateAfterSend($result){
        if(str_starts_with($result, 'Sorry, there was an error moving the file.')){
            return false;
        }
        return true;
    }

    public function downloadXML(){
        $tempCode = MasterResponseTemplates::find($this->templateId);
        $fileName = $this->xmlData['DeclarationNumber']??''.'-'.$tempCode->code.'-'.str_replace("/","-",$this->xmlData['Message']).'.xml';
        $xmlContent = $this->xmlContent; 
        \Storage::disk('public')->put($fileName, $xmlContent);
        $this->emit('fileManualDownload', asset('storage/' . $fileName));
    }

    public function selectMessage($masterMsgId) {
        $message = MasterResponseMessageType::where('id', $masterMsgId)->first();
        $this->xmlData["Message"] = $message->message;
        $this->reGenerateXML();
        $this->showSearch = false;
    }

    public function updatedXmlData($value, $key)
    {
        if ($key === 'Message') {
            $this->showSearch = true;
            $tempCode = MasterResponseTemplates::find($this->templateId);
            $tempDoc = MasterMessages::find($this->messageId);

            if ($tempCode && $tempDoc) {
                $message = MasterResponseMessageType::where('doctype', strtoupper($tempDoc->name))
                    ->where('codestatus', $tempCode->code)
                    ->where('message', 'like', '%' . $value . '%')
                    ->get();
            } else {
                $message = collect(); // Return an empty collection if no data is found
            }

            $this->masterMsg = $message;
        }
      
    }
}
