<?php

namespace LaraBB\User\Actions\Admin;

use Illuminate\Database\Connection;
use JetBrains\PhpStorm\ArrayShape;
use LaraBB\User\Models\User;
use LaraBB\User\Tasks\FindTask as FindUserTask;
use LaraBB\User\Tasks\UpdateTask as UpdateUserTask;
use LaraBB\User\UI\Web\Requests\Update;
use Ramsey\Uuid\Uuid;
use Throwable;

/**
 * Class UpdateAction
 * @package LaraBB\User\Actions\Admin
 */
class UpdateAction
{
    /**
     * UpdateAction constructor.
     * @param FindUserTask $findUserTask
     * @param UpdateUserTask $updateUserTask
     * @param Connection $connection
     */
    public function __construct(
        private readonly FindUserTask $findUserTask,
        private readonly UpdateUserTask $updateUserTask,
        private readonly Connection $connection
    ) {
    }

    /**
     * @param Update $request
     * @return bool
     */
    public function run(Update $request): bool
    {
        $user = $this->findUserTask->byUuid($request->post('uuid'));

        try {
            $this->connection->transaction(function () use ($user, $request) {
                $this->updateUserTask->run($user, $this->prepareUserData($request, $user));
            });
        } catch (Throwable $t) {
            return false;
        }

        return true;
    }

    /**
     * @param Update $request
     * @param User $user
     * @return array
     */
    #[ArrayShape([
        'updated_uuid'            => "mixed",
        'deactivated_at'          => "\Illuminate\Support\Carbon|null",
        'deactivated_uuid'        => "mixed",
        'username'                => "array|null|string",
        'email_hashed'            => "array|null|string",
        'email_encrypted'         => "array|null|string",
        'password'                => "array|string",
        'passwordchange_required' => "bool",
        'groups'                  => "array"
    ])] private function prepareUserData(Update $request, User $user): array
    {
        return [
            'updated_uuid'            => $request->user()->uuid,
            'deactivated_at'          => $request->has('account-disabled') ? now() : null,
            'deactivated_uuid'        => $request->has('account-disabled') ? $request->user()->uuid : null,
            'username'                => $request->post('username'),
            'email_hashed'            => $request->post('email'),
            'email_encrypted'         => $request->post('email'),
            'password'                => $request->post('password') ?? $user->password,
            'passwordchange_required' => $request->has('force-password-change'),
            'groups'                  => $this->prepareGroupData($request)
        ];
    }

    /**
     * @param Update $request
     * @return array
     */
    private function prepareGroupData(Update $request): array
    {
        $return = [];

        foreach ($request->post('groups') as $group) {
            $return[$group] = [
                'uuid'         => Uuid::uuid4(),
                'created_at'   => now(),
                'created_uuid' => $request->user()->uuid,
                'updated_at'   => now(),
                'updated_uuid' => $request->user()->uuid
            ];
        }

        return $return;
    }
}
