<?php

namespace LaraBB\User\Actions\Admin;

use Hash;
use Illuminate\Database\Connection;
use JetBrains\PhpStorm\ArrayShape;
use LaraBB\Profile\Tasks\StoreTask as StoreProfileTask;
use LaraBB\User\Models\User;
use LaraBB\User\Tasks\StoreTask as StoreUserTask;
use LaraBB\User\UI\Web\Requests\Store;
use Ramsey\Uuid\Uuid;
use Throwable;

/**
 * Class StoreAction
 * @package LaraBB\User\Actions\Admin
 */
class StoreAction
{
    /**
     * StoreAction constructor.
     * @param StoreUserTask $storeUserTask
     * @param StoreProfileTask $storeProfileTask
     * @param Connection $connection
     */
    public function __construct(
        private readonly StoreUserTask $storeUserTask,
        private readonly StoreProfileTask $storeProfileTask,
        private readonly Connection $connection
    ) {

    }

    /**
     * @param Store $request
     * @return bool
     */
    public function run(Store $request): bool
    {
        try {
            $this->connection->transaction(function() use($request) {
                $user = $this->storeUserTask->run($this->prepareUserData($request));
                $this->storeProfileTask->run($this->prepareProfileData($request, $user));
            });
        } catch(Throwable $t) {
            return false;
        }

        return true;
    }

    /**
     * @param Store $request
     * @return array
     */
    private function prepareUserData(Store $request): array
    {
        return [
            'pid'                     => md5(uniqid(mt_rand(), true)),
            'created_uuid'            => $request->user()->uuid,
            'updated_uuid'            => $request->user()->uuid,
            'deactivated_at'          => $request->has('account-disabled') ? now() : null,
            'deactivated_uuid'        => $request->has('account-disabled') ? $request->user()->uuid : null,
            'registered_at'           => now(),
            'registered_ip'           => $request->ip(),
            'username'                => $request->post('username'),
            'email_hashed'            => $request->post('email'),
            'email_encrypted'         => $request->post('email'),
            'password'                => Hash::make($request->post('password')),
            'passwordchange_required' => $request->has('force-password-change'),
            'groups'                  => $this->prepareGroupData($request)
        ];
    }

    /**
     * @param Store $request
     * @return array
     */
    private function prepareGroupData(Store $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;
    }

    /**
     * @param Store $request
     * @param User $user
     * @return array
     */
    #[ArrayShape([
        'user_uuid'    => "string",
        'created_uuid' => "mixed",
        'updated_uuid' => "mixed"
    ])]
    private function prepareProfileData(Store $request, User $user): array
    {
        return [
            'user_uuid'    => $user->uuid,
            'created_uuid' => $request->user()->uuid,
            'updated_uuid' => $request->user()->uuid,
        ];
    }
}
