<?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\Core\Role\Modals;


use BplanBase\Globals\Models\Role;
use BplanBase\Globals\Services\RoleService;
use BplanBase\Globals\Traits\InteractsWithBanner;
use Livewire\Attributes\On;
use Livewire\Attributes\Validate;
use Livewire\Component;
use Spatie\Permission\Models\Permission;


/**
 * Livewire Component
 *
 * @version     1.0.0 / 2026-06-07
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 */
class Edit extends Component
{


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


    use InteractsWithBanner;


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


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


    /**
     * @var     bool
     */
    public bool $active = true;


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


    /**
     * @var     array|null
     */
    #[Validate('required')]
    public ?array $labelsJson = null;


    /**
     * @var     string
     */
    public string $locale;


    /**
     * @var     string
     */
    #[Validate('required|string|max:255')]
    public string $name = '';


    /**
     * Permission matrix: key = "package.resource.action", value = bool
     *
     * @var     array<string, bool>
     */
    public array $permissionMatrix = [];


    /**
     * All permissions grouped by package → resource for rendering the matrix.
     *
     * @var     array<string, array<string, array<string, int>>>
     */
    public array $permissionGroups = [];


    /**
     * All distinct action columns present in the permission set.
     *
     * @var     array<string>
     */
    public array $permissionActions = [];


    /**
     * @var     Role|null
     */
    public ?Role $Role = null;


    /**
     * @var     RoleService
     */
    protected RoleService $RoleService;


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


    /**
     * @var     string
     */
    private static string $_logPrefix = 'Core/Role/Modals/Edit';


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


    /**
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function boot(RoleService $RoleService)
    {
        $this->RoleService = $RoleService;

        $this->locale = app()->getLocale();

    } // boot()


    /**
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function editRole()
    {
        if ($this->internal === true) {
            return;
        }

        $this->validate();

        try {
            $this->RoleService->update($this->Role->id, [
                'active'     => $this->active,
                'labels'     => $this->labelsJson,
                'name'       => $this->name,
            ]);

            $activePermissions = [];
            foreach ($this->permissionMatrix as $resource => $actionMap) {
                foreach ($actionMap as $action => $checked) {
                    if ($checked === true) {
                        $activePermissions[] = $resource.'.'.$action;
                    }
                }
            }
            $this->Role->syncPermissions($activePermissions);

            $User = auth()->user();

            \AppLog::info('Role ['.$this->name.'] edited by ['.$User->name.' ('.$User->email.')]', self::$_logPrefix);

            $this->dispatch('init-tippyjs');
            $this->dispatch('role-saved');

        } catch (\Throwable $th) {
            \AppLog::error($th, self::$_logPrefix);

            $this->dangerBanner('Error when editing role. Check the logs for more information.');
        }

    } // editRole()


    /**
     *
     * @param       array|null $json
     *
     * @param       string $target
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    #[On('multi-language-json-created')]
    public function onMultiLanguageJsonCreated(?array $json, string $target): void
    {
        if ($target === 'edit') {
            $this->labelsJson = $json;
        }

    } // onMultiLanguageJsonCreated()


    /**
     *
     * @param       array $role
     *              Array with key 'id' from the DataGrid action event.
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    #[On('show-edit-role-modal')]
    public function initRole(array $role)
    {
        $this->Role = Role::with('permissions')->find($role['id']);

        $this->active     = $this->Role->active;
        $this->internal   = $this->Role->internal;
        $this->labelsJson = (array) $this->Role->labels;
        $this->name       = $this->Role->name;

        $this->_buildPermissionMatrix();

        $this->dispatch('init-tippyjs');

    } // initRole()


    /**
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function render()
    {
        return view('globals::livewire.core.role.modals.edit', [
            'permissionActions' => $this->permissionActions,
            'permissionGroups'  => $this->permissionGroups,
        ]);

    } // render()


    /**
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function resetModal()
    {
        $this->active             = true;
        $this->internal           = false;
        $this->labelsJson         = null;
        $this->name               = '';
        $this->permissionActions  = [];
        $this->permissionGroups   = [];
        $this->permissionMatrix   = [];
        $this->Role               = null;

    } // resetModal()


    /**
     * Builds $permissionGroups and $permissionMatrix from all available permissions.
     *
     * $permissionMatrix is nested as [resource][action] = bool so that Livewire's
     * dot-notation wire:model="permissionMatrix.resource.action" works correctly.
     * Resource names are unique across packages in this application.
     *
     * @version     1.0.0 / 2026-06-07
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _buildPermissionMatrix(): void
    {
        $rolePermissionNames = $this->Role->permissions->pluck('name')->flip()->toArray();

        $actions = [];
        $groups  = [];

        $AllPermissions = Permission::orderBy('package')->orderBy('name')->get();

        foreach ($AllPermissions as $Permission) {
            $parts    = explode('.', $Permission->name);
            $resource = $parts[0] ?? $Permission->name;
            $action   = $parts[1] ?? '';
            $package  = $Permission->package ?? 'other';

            if (isset($groups[$package]) === false) {
                $groups[$package] = [];
            }
            if (isset($groups[$package][$resource]) === false) {
                $groups[$package][$resource] = [];
            }

            $groups[$package][$resource][$action] = $Permission->id;
            $actions[$action]                     = true;

            if (isset($this->permissionMatrix[$resource]) === false) {
                $this->permissionMatrix[$resource] = [];
            }
            $this->permissionMatrix[$resource][$action] = isset($rolePermissionNames[$Permission->name]);
        }

        ksort($actions);

        $this->permissionActions = array_keys($actions);
        $this->permissionGroups  = $groups;

    } // _buildPermissionMatrix()


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


} // class Edit extends Component {}
