<?php

namespace App\PackagesApi\v3\Controllers\Capsule;

use App\Http\Controllers\Controller;
use App\Packages\Capsule\Models\Capsule;
use App\Packages\Capsule\Models\CapsuleComment;
use App\Packages\Capsule\Models\CapsuleLike;
use App\Packages\Capsule\Repository\CapsuleCommentRepository;
use App\Packages\Capsule\Repository\CapsuleLikeRepository;
use App\Packages\Capsule\Repository\CapsuleRepository;
use App\Packages\Capsule\Services\CapsuleService;
use App\Packages\Capsule\Transformer\CapsuleArrayTransformer;
use App\Packages\Capsule\Transformer\CapsuleCommentTransformer;
use App\Packages\User\Models\User;
use App\Packages\User\Service\UserMentionService;
use App\Packages\User\Services\CapsuleAdditionalService;
use App\Packages\User\Transformer\UserTransformer;
use App\PackagesApi\v3\Requests\Capsule\CommentDeleteRequest;
use App\PackagesApi\v3\Requests\Capsule\CommentRequest;
use App\PackagesApi\v3\Requests\Capsule\CommentUpdateRequest;
use App\PackagesApi\Status\StatusCode;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Class InfoController
 * @package App\PackagesApi\Controllers\v3
 */
class InfoController extends Controller
{
    /** @var Capsule */
    private $capsule;

    /** @var User */
    private $user;

    /**
     * CapsuleController constructor.
     *
     * @param Request $request
     */
    public function __construct(Request $request)
    {
        $this->middleware(function (Request $request, $next) {

            $capsuleUuid = $request->get('capsule_id') ?? $request->route('capsule_id');
            $capsule = CapsuleRepository::init()->firstByUuid($capsuleUuid);

            if (!$capsule) {
                return jsonErrorEntity([
                    'message' => trans('api.msg.capsule_does_not_exists'),
                ]);
            }

            $this->capsule = $capsule;
            $this->user = user();

            return $next($request);
        });
    }

    /**
     * @return JsonResponse
     */
    public function info()
    {
        return jsonSuccess([
            'capsule' => CapsuleArrayTransformer::mainCapsule($this->capsule, $this->user),
        ]);
    }

    /**
     * @return JsonResponse
     */
    public function likesList()
    {
        $this->user->saveAccess('View like list');

        $capsuleLikes = CapsuleLikeRepository::init()->capsuleLikes($this->capsule);
        $capsuleLikes = $capsuleLikes->map(function (User $user) {
            return UserTransformer::smallObject($user);
        });

        return jsonSuccess([
            'users' => $capsuleLikes,
        ]);
    }

    /**
     * @param CapsuleAdditionalService $service
     * @return JsonResponse
     */
    public function subscriberList(CapsuleAdditionalService $service)
    {
        $this->user->saveAccess('View capsule subscribers list');

        return jsonSuccess([
            'users' => $service->getCapsuleSubscribedUsers($this->capsule),
        ]);
    }

    /**
     * @return JsonResponse
     */
    public function comments()
    {
        $this->user->saveAccess('View capsule comments list');

        $comments = CapsuleCommentRepository::init()->capsuleComments($this->capsule);
        $comments = $comments->map(function (CapsuleComment $comment) {
            return CapsuleCommentTransformer::commentFull($comment, $this->user);
        });

        return jsonSuccess([
            'comments' => $comments,
        ]);
    }




    // Manipulation mehtods

    /**
     * @return JsonResponse
     */
    public function open()
    {
        $this->user->saveAccess('Open capsule');

        if (!$this->capsule->canBeOpened()) {
            return jsonErrorEntity([
                'message' => 'Capsule can not be opened yet',
            ]);
        }

        $capsuleUpdateService = new CapsuleService($this->capsule);
        $capsuleUpdateService->openCapsule($this->user);

        return jsonSuccess([
            'capsule' => CapsuleArrayTransformer::mainCapsule($this->capsule, $this->user),
        ]);
    }

    /**
     * @return JsonResponse
     *
     * @throws \Exception
     */
    public function like()
    {
        $this->user->saveAccess('Like/Unlike capsule');

        $capsuleUpdateService = new CapsuleService($this->capsule);
        $capsuleUpdateService->toggleLike($this->user);

        return jsonSuccess([
            'capsule' => CapsuleArrayTransformer::mainCapsule($this->capsule, $this->user),
        ]);
    }



    /**
     * @return JsonResponse
     *
     * @throws \Exception
     */
    public function subscribe()
    {
        $this->user->saveAccess('Subscribe/Unsubscribe capsule');

        $capsuleUpdateService = new CapsuleService($this->capsule);
        $capsuleUpdateService->toggleSubscriber($this->user);

        return jsonSuccess([
            'capsule' => CapsuleArrayTransformer::mainCapsule($this->capsule, $this->user),
        ]);
    }



    /**
     * @param CommentRequest $request
     *
     * @return JsonResponse
     */
    public function addComment(CommentRequest $request)
    {
        $this->user->saveAccess('Add comment to capsule');

        // can comment, how much comments, and so on

        $capsuleUpdateService = new CapsuleService($this->capsule);
        $comment = $capsuleUpdateService->addComment($this->user, $request->content);

        UserMentionService::processComment($comment);

        return jsonSuccess([
            'comment' => CapsuleCommentTransformer::commentFull($comment, $this->user),
        ]);
    }

    public function editComment(CommentUpdateRequest $request)
    {
        $this->user->saveAccess('Edit comment to capsule');
        /** @var CapsuleComment $comment */
        $comment = CapsuleCommentRepository::init()->firstByUuid($request->comment_id);

        /** check if user can update comment */
        if ( ! $comment ) return jsonErrorMessage('Comment not found');
        if ( $this->user->id != $comment->user_id )
            return jsonError(
                ['message' => 'User cannot edit comment'],
                StatusCode::HTTP_METHOD_NOT_ALLOWED
            );

        $capsuleUpdateService = new CapsuleService($this->capsule);
        $comment = $capsuleUpdateService->editComment($comment, $request->content);

        UserMentionService::processComment($comment);

        return jsonSuccess([
            'comment' => CapsuleCommentTransformer::commentFull($comment, $this->user),
        ]);
    }

    public function deleteComment(CommentDeleteRequest $request)
    {
        $this->user->saveAccess('Delete comment to capsule');
        /** @var CapsuleComment $comment */
        $comment = CapsuleCommentRepository::init()->firstByUuid($request->comment_id);

        /** check if user can delete comment */
        if ( ! $comment ) return jsonErrorMessage('Comment not found');
        if ( ! ($this->user->id == $comment->user_id || $this->user->id == $this->capsule->user_id) )
            return jsonError(
                ['message' => 'User cannot delete comment'],
                StatusCode::HTTP_METHOD_NOT_ALLOWED
            );

        $capsuleUpdateService = new CapsuleService($this->capsule);
        $capsuleUpdateService->deleteComment($comment);

        return jsonSuccess();
    }
}
