<?php

namespace App\PackagesApi\v3\Controllers\Feed;

use App\Http\Controllers\Controller;
use App\Packages\Capsule\Models\Capsule;
use App\Packages\Capsule\Models\CapsuleRemoved;
use App\Packages\Capsule\Models\CapsuleTaggedUser;
use App\Packages\Capsule\Repository\CapsuleRemovedRepository;
use App\Packages\Capsule\Repository\CapsuleRepository;
use App\Packages\Capsule\Repository\CapsuleTaggedUserRepository;
use App\Packages\Capsule\Services\CapsuleFeedService;
use App\Packages\Capsule\Transformer\CapsuleArrayTransformer;
use App\Packages\User\Models\User;
use App\PackagesApi\v3\Requests\Capsule\CancelRequest;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Class FeedController
 *
 * @package App\Http\Controllers\API
 */
class FeedController extends Controller
{
    /** @var User */
    private $user;

    /** @var CapsuleFeedService */
    private $feedService;

    public function __construct(CapsuleFeedService $feedService)
    {
        $this->user = user();
        $this->feedService = $feedService;
    }

    /**
     * @return JsonResponse
     */
    public function timelineInitial()
    {
        $this->user->saveAccess('View user feed');

        $capsulesLeft = 10;
        $capsules = collect();

        // Past capsules
        $pastCapsules = $this->feedService->getPastCapsules($this->user, null, 3);
        $pastCapsules = $pastCapsules->sortBy('open_at');

        $capsules = $capsules->merge($pastCapsules);
        $capsulesLeft -= $pastCapsules->count();


        $futureCapsules = $this->feedService->getFutureCapsules($this->user, null, $capsulesLeft);
        $capsules = $capsules->merge($futureCapsules);

        $user = $this->user;
        $capsules = $capsules->map(
            function ($capsule) use ($user) {
                return CapsuleArrayTransformer::feedCapsuleArray($capsule, $user);
            }
        );

        $totalPast = $this->feedService->getPastCapsulesCount($this->user);
        $totalFuture = $this->feedService->getFutureCapsulesCount($this->user);

        return jsonSuccess(
            [
                'total_past' => (int)($totalPast - $pastCapsules->count()),
                'total_future' => (int)($totalFuture - $futureCapsules->count()),
                'capsules' => $capsules,
            ]
        );
    }

    /**
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function timeLinePast(Request $request)
    {
        $this->user->saveAccess('Get only opened capsules feed');

        $fromDate = $request->get('from_date');

        $capsules = collect();

        $user = $this->user;
        $openedCapsules = $this->feedService->getPastCapsules($this->user, $fromDate);
        $openedCapsules = $openedCapsules->sortBy('open_at');

        $capsules = $capsules->merge($openedCapsules);
        $capsules = $capsules->map(
            function ($capsule) use ($user) {
                return CapsuleArrayTransformer::feedCapsuleArray($capsule, $user);
            }
        );

        $totalCount = $this->feedService->getPastCapsulesCount($this->user, $fromDate);

        return jsonSuccess(
            [
                'total_count' => (int)($totalCount - $capsules->count()),
                'capsules' => $capsules,
            ]
        );

    }

    /**
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function timeLineFuture(Request $request)
    {
        $this->user->saveAccess('Get only hatched and locked capsules feed');

        $user = $this->user;
        $fromDate = $request->get('from_date');

        $capsules = $this->feedService->getFutureCapsules($user, $fromDate);
        $capsules = $capsules->map(
            function ($capsule) use ($user) {
                return CapsuleArrayTransformer::feedCapsuleArray($capsule, $user);
            }
        );

        $totalCount = $this->feedService->getFutureCapsulesCount($user, $fromDate);

        return jsonSuccess(
            [
                'total' => $totalCount,
                'count' => $capsules->count(),
                'total_count' => (int)($totalCount - $capsules->count()),
                'capsules' => $capsules,
            ]
        );
    }

    /**
     * @param CancelRequest $request
     *
     * @return JsonResponse
     *
     * @throws \Exception
     */
    public function removeTag(CancelRequest $request)
    {
        $this->user->saveAccess('Remove user tag');

        $capsule = CapsuleRepository::init()->firstByUuid($request->capsule_id);
        if (!$capsule) {
            return jsonErrorEntity([
                'message' => trans('api.msg.capsule_does_not_exists'),
            ]);
        }

        if ($capsule->user_id == $this->user->id) {
            return jsonErrorEntity([
                'message' => 'Can not remove tagged user',
            ]);
        }

        $taggedUser = CapsuleTaggedUserRepository::init()->getTaggedUser($capsule, $this->user);
        $taggedUser->delete();

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

    /**
     * @param CancelRequest $request
     *
     * @return JsonResponse
     *
     * @throws \Exception
     */
    public function remove(CancelRequest $request)
    {
        $this->user->saveAccess('Remove capsule from our feed');

        $capsule = CapsuleRepository::init()->firstByUuid($request->capsule_id);
        if (!$capsule) {
            return jsonErrorEntity([
                'message' => trans('api.msg.capsule_does_not_exists'),
            ]);
        }

        /** @var CapsuleRemoved $relation */
        $relation = CapsuleRemovedRepository::init()->capsuleRelation($capsule, $this->user);
        if (!$relation) {
            /** Remove from timeline */
            CapsuleRemoved::createRelation($capsule, $this->user);
        } else {
            $relation->delete();
        }

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