<?php
/**
 * Livewire Component
 *
 * @version     1.0.0
 * @package     bplan-base/globals
 * @subpackage  LivewireComponents
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 * @copyright   Copyright (C) 2025, 2026 bplan-solutions GmbH & Co. KG <https://www.bplan-solutions.de/>
 * /Δ\
 */

namespace BplanBase\Globals\Livewire\DynamicForm;


use BplanBase\Globals\Registries\DynamicFormRegistry;
use BplanBase\Globals\Traits\ProcessesConfigTemplate;
use Livewire\Component;


/**
 * Livewire Component
 *
 * Interaktiver Designer für JSON-basierte Dynamic-Form-Konfigurationen.
 * Erlaubt das Bearbeiten eines config_template-Felds direkt aus der
 * Datenbank — mit Live-Vorschau und Debug-Ansicht der aufbereiteten Struktur.
 *
 * @version     1.0.0 / 2026-05-24
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 */
class Designer extends Component
{


/* +++ TRAITS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */


    use ProcessesConfigTemplate;


/* +++ CLASS CONSTANTS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT MEMBERS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * @var     array
     */
    public array $configSections = [];


    /**
     * @var     string
     */
    public string $configTemplateJson = '';


    /**
     * @var     string
     */
    public string $display = 'sections';


    /**
     * @var     bool
     */
    public bool $jsonIsValid = false;


    /**
     * @var     string
     */
    public string $saveMessage = '';


    /**
     * @var     string  'success'|'error'|''
     */
    public string $saveMessageType = '';


    /**
     * @var     string|null
     */
    public ?string $selectedRecordId = null;


    /**
     * @var     string
     */
    public string $selectedSource = '';


    /**
     * @var     array
     */
    public array $testData = [];


    /**
     * @var     array|null
     */
    public ?array $preparedTemplate = null;


    /**
     * @var     string
     */
    public string $wireModelPrefix = 'testData';


/* +++ CLASS MEMBERS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT METHODS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * Gibt alle Records der gewählten Quelle für das Datensatz-Dropdown zurück.
     *
     * @return      array<int|string, string>
     *
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function getRecordsProperty(): array
    {
        $source = DynamicFormRegistry::get($this->selectedSource);

        if ($source === null) {
            return [];
        }

        $modelClass  = $source['modelClass'];
        $labelColumn = $source['labelColumn'];

        return $modelClass::orderBy($labelColumn)->pluck($labelColumn, 'id')->toArray();

    } // getRecordsProperty()


    /**
     * Gibt alle registrierten Quellen für das Quellen-Dropdown zurück.
     *
     * @return      array<string, string>
     *
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function getSourcesProperty(): array
    {
        return array_map(
            fn ($entry) => $entry['displayName'],
            DynamicFormRegistry::all()
        );

    } // getSourcesProperty()


    /**
     * Lädt den config_template-Wert des gewählten Datensatzes in die JSON-Textarea.
     *
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function loadFromDb(): void
    {
        $source = DynamicFormRegistry::get($this->selectedSource);

        if ($source === null || $this->selectedRecordId === null) {
            return;
        }

        $modelClass = $source['modelClass'];
        $field      = $source['field'];
        $Record     = $modelClass::find($this->selectedRecordId);

        if ($Record === null) {
            return;
        }

        $raw = $Record->getRawOriginal($field);

        if ($raw === null || $raw === '') {
            $this->configTemplateJson = '';
        } else {
            $decoded = is_string($raw) ? json_decode($raw) : $raw;
            $this->configTemplateJson = $decoded !== null
                ? json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
                : (string) $raw;
        }

        $this->_clearSaveMessage();
        $this->_process();

    } // loadFromDb()


    /**
     * Lädt die Beispiel-Konfiguration aus der Klasse in die JSON-Textarea.
     *
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function loadExample(): void
    {
        $this->configTemplateJson = $this->_buildExampleJson();
        $this->_clearSaveMessage();
        $this->_process();

    } // loadExample()


    /**
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function mount(): void
    {
        $this->configTemplateJson = $this->_buildExampleJson();
        $this->_process();

    } // mount()


    /**
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function render()
    {
        return view('globals::livewire.dynamic-form.designer');

    } // render()


    /**
     * Schreibt den aktuellen JSON-Stand zurück in das DB-Feld des gewählten Datensatzes.
     * Wird nur ausgeführt wenn das JSON gültig ist.
     *
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function saveToDb(): void
    {
        if ($this->jsonIsValid === false) {
            $this->saveMessage     = trans('globals::dynamic-form.designer.message.invalid-json');
            $this->saveMessageType = 'error';
            return;
        }

        $source = DynamicFormRegistry::get($this->selectedSource);

        if ($source === null || $this->selectedRecordId === null) {
            return;
        }

        $modelClass = $source['modelClass'];
        $field      = $source['field'];
        $Record     = $modelClass::find($this->selectedRecordId);

        if ($Record === null) {
            return;
        }

        /*
        **  Direkter Query-Builder-Aufruf um Eloquent-Casts zu umgehen.
        **  Würde man $Record->{$field} setzen und save() aufrufen, würde ein
        **  object/array-Cast den JSON-String nochmals encodieren. */
        $modelClass::where('id', $this->selectedRecordId)->update([$field => $this->configTemplateJson]);

        $this->saveMessage     = trans('globals::dynamic-form.designer.message.saved');
        $this->saveMessageType = 'success';

    } // saveToDb()


    /**
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function updated(string $property): void
    {
        if ($property === 'selectedSource') {
            $this->selectedRecordId = null;
            $this->_clearSaveMessage();
        }

        if ($property === 'selectedRecordId') {
            $this->_clearSaveMessage();
        }

        if ($property === 'configTemplateJson' || $property === 'display') {
            $this->_clearSaveMessage();
            $this->_process();
        }

    } // updated()


/* +++ CLASS METHODS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _buildExampleJson(): string
    {
        return json_encode([
            '.meta' => [
                /*
                'labels' => [
                    'de' => [
                        'active'                   => 'Aktiv',
                        'company'                  => 'Firma',
                        'email'                    => 'E-Mail-Adresse',
                        'first_name'               => 'Vorname',
                        'host'                     => 'Hostname',
                        'last_name'                => 'Nachname',
                        'notes'                    => 'Notizen',
                        'phone_number'             => 'Telefonnummer',
                        'port'                     => 'Port',
                        'protocol'                 => 'Protokoll',
                        'section.contact'          => 'Kontaktdaten',
                        'section.default'          => 'Allgemein',
                        'section.general'          => 'Allgemein',
                        'section.network'          => 'Netzwerk',
                        'section.network.basic'    => 'Basis',
                        'section.network.advanced' => 'Erweitert',
                        'timeout'                  => 'Timeout (s)',
                    ],
                    'en' => [
                        'active'                   => 'Active',
                        'company'                  => 'Company',
                        'email'                    => 'E-Mail Address',
                        'first_name'               => 'First name',
                        'host'                     => 'Hostname',
                        'last_name'                => 'Last name',
                        'notes'                    => 'Notes',
                        'phone_number'             => 'Phone number',
                        'port'                     => 'Port',
                        'protocol'                 => 'Protocol',
                        'section.contact'          => 'Contact data',
                        'section.default'          => 'General',
                        'section.general'          => 'General',
                        'section.network'          => 'Network',
                        'section.network.basic'    => 'Basic',
                        'section.network.advanced' => 'Advanced',
                        'timeout'                  => 'Timeout (s)',
                    ],
                ],
                */
                'labels' => 'globals::dynamic-form.designer-example-labels',
                'order' => [
                    'company',
                    '_',
                    'first_name',
                    'last_name',
                    'phone_number',
                    'email',
                    'active',
                    '_',
                    'protocol',
                    'host',
                    'port',
                    'timeout',
                ],
                'sectionorder' => [
                    'general',
                    'contact',
                    'network',
                    'network.basic',
                    'network.advanced',
                ],
            ],
            'active' => [
                'section' => 'network.basic',
                'type'    => 'toggle',
            ],
            'company' => [
                'mandatory' => true,
                'section'   => 'general',
                'type'      => 'string',
            ],
            'email' => [
                'section' => 'contact',
                'type'    => 'string',
            ],
            'first_name' => [
                'mandatory' => true,
                'section'   => 'general',
                'type'      => 'string',
            ],
            'host' => [
                'mandatory' => true,
                'section'   => 'network.basic',
                'type'      => 'string',
            ],
            'last_name' => [
                'mandatory' => true,
                'section'   => 'general',
                'type'      => 'string',
            ],
            'notes' => [
                'fullwidth' => true,
                'section'   => 'general',
                'type'      => 'textarea',
            ],
            'phone_number' => [
                'section' => 'contact',
                'type'    => 'string',
            ],
            'port' => [
                'default'   => 80,
                'mandatory' => true,
                'min'       => 1,
                'section'   => 'network.basic',
                'type'      => 'number',
            ],
            'protocol' => [
                'options' => [
                    'TCP',
                    'UDP',
                    'HTTP',
                    'HTTPS'
                ],
                'section' => 'network.basic',
                'type'    => 'select',
            ],
            'timeout' => [
                'max'     => 300,
                'min'     => 0,
                'section' => 'network.advanced',
                'step'    => 5,
                'type'    => 'number',
            ],

        ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

    } // _buildExampleJson()


    /**
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _clearSaveMessage(): void
    {
        $this->saveMessage     = '';
        $this->saveMessageType = '';

    } // _clearSaveMessage()


    /**
     * @version     1.0.0 / 2026-05-24
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _process(): void
    {
        $json = trim($this->configTemplateJson);

        if ($json === '') {
            $this->preparedTemplate = null;
            $this->configSections   = [];
            $this->jsonIsValid      = false;
            return;
        }

        json_decode($json);
        $this->jsonIsValid = json_last_error() === JSON_ERROR_NONE;

        if ($this->jsonIsValid === false) {
            $this->preparedTemplate = null;
            $this->configSections   = [];
            return;
        }

        $result                 = $this->_prepareConfigTemplate($json);
        $this->preparedTemplate = $result['template'];
        $this->configSections   = $result['sections'];
        $this->testData         = $this->_applyConfigDefaults($this->preparedTemplate, $this->testData);

    } // _process()


} // class Designer extends Component {}
