<?php

namespace LaraBB\Forum\Actions\Admin;

use Illuminate\Database\Connection;
use JetBrains\PhpStorm\ArrayShape;
use LaraBB\Forum\Tasks\Forum\FindTask as FindForumTask;
use LaraBB\Forum\Tasks\Forum\UpdateTask as UpdateForumTask;
use LaraBB\Forum\Tasks\Permission\UpdateTask as UpdateForumPermissionTask;
use LaraBB\Forum\Tasks\User\UpdateTask as UpdateForumUserTask;
use Illuminate\Database\Eloquent\Collection;
use LaraBB\Forum\UI\Web\Requests\Update;
use Ramsey\Uuid\Uuid;
use Throwable;

/**
 * Class UpdateAction
 * @package LaraBB\Forum\Actions\Admin
 */
class UpdateAction
{
    /**
     * UpdateAction constructor.
     * @param FindForumTask $findForumTask
     * @param UpdateForumTask $updateForumTask
     * @param UpdateForumPermissionTask $updateForumPermissionTask
     * @param UpdateForumUserTask $updateForumUserTask
     * @param Connection $connection
     */
    public function __construct(
        private readonly FindForumTask $findForumTask,
        private readonly UpdateForumTask $updateForumTask,
        private readonly UpdateForumPermissionTask $updateForumPermissionTask,
        private readonly UpdateForumUserTask $updateForumUserTask,
        private readonly Connection $connection
    ) {
    }

    /**
     * @param Update $request
     * @return bool
     */
    public function run(Update $request): bool
    {
        $forum = $this->findForumTask->byUuid($request->post('uuid'), [
            'users',
            'permissions'
        ]);

        try {
            $this->connection->transaction(function() use($forum, $request) {
                $this->updateForumPermissionTask->run($forum->permissions, $this->prepareForumPermissionData($forum->permissions, $request));
                $this->updateForumUserTask->run($forum, $this->prepareForumUsersData($request));
                $this->updateForumTask->run($forum, $this->prepareForumData($request));
            });
        } catch(Throwable $t) {
            return false;
        }

        return true;


    }

    /**
     * @param Update $request
     * @return array
     */
    #[ArrayShape([
        'category_uuid' => "array|null|string",
        'updated_uuid'  => "mixed",
        'title'         => "array|null|string",
        'description'   => "array|null|string",
        'slug'          => "array|null|string"
    ])]
    private function prepareForumData(Update $request): array
    {
        return [
            'category_uuid' => $request->post('category'),
            'updated_uuid'  => $request->user()->uuid,
            'title'         => $request->post('title'),
            'description'   => $request->post('description'),
            'slug'          => $request->post('slug')
        ];
    }

    /**
     * @param Collection $forumPermissions
     * @param Update $request
     * @return array
     */
    private function prepareForumPermissionData(Collection $forumPermissions, Update $request): array
    {
        if (!$request->has('permissions')) {
            return [];
        }

        $permissions = [];

        foreach ($request->post('permissions') as $groupUuid => $groupPermissions) {
            $permissionUuid = $forumPermissions->where('group_uuid', $groupUuid)->first()->uuid;

            $permissions[$permissionUuid] = [
                'updated_uuid'   => $request->user()->uuid,
                'show_forum'     => $groupPermissions['show_forum'] ?? 0,
                'show_threads'   => $groupPermissions['show_threads'] ?? 0,
                'show_posts'     => $groupPermissions['show_posts'] ?? 0,
                'create_threads' => $groupPermissions['create_threads'] ?? 0,
                'create_posts'   => $groupPermissions['create_posts'] ?? 0,
                'edit_threads'   => $groupPermissions['edit_threads'] ?? 0,
                'edit_posts'     => $groupPermissions['edit_posts'] ?? 0,
                'delete_threads' => $groupPermissions['delete_threads'] ?? 0,
                'delete_posts'   => $groupPermissions['delete_posts'] ?? 0
            ];
        }

        return $permissions;
    }

    /**
     * @param Update $request
     * @return array
     */
    private function prepareForumUsersData(Update $request): array
    {
        if(!$request->has('users')) {
            return [];
        }

        $return = [];

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

        return $return;
    }
}
