<?php

namespace App\PackagesApi\v3\Controllers\User;

use App\Http\Controllers\Controller;
use App\Packages\Core\Exceptions\RecordNotExistsException;
use App\Packages\Phone\Service\VerificationCodeService;
use App\Packages\User\Manager\DemoUserManager;
use App\Packages\User\Manager\TokenManager;
use App\Packages\User\Manager\UserEntityManager;
use App\Packages\User\Models\User;
use App\Packages\User\Models\UserPhoneConfirm;
use App\Packages\User\Repository\UserRepository;
use App\PackagesApi\v3\Requests\Auth\PhoneCodeRequest;
use App\PackagesApi\v3\Requests\Auth\PhoneRequest;
use Illuminate\Http\JsonResponse;

/**
 * Class AuthController
 *
 * @package App\PackagesApi\Controllers\v3
 */
class AuthController extends Controller
{
    /** @var VerificationCodeService */
    private $verificationCodeService;

    public function __construct(VerificationCodeService $verificationCodeService)
    {
        $this->verificationCodeService = $verificationCodeService;
    }

    /**
     * @param PhoneRequest $request
     *
     * @return JsonResponse
     */
    public function sendPhoneCode(PhoneRequest $request)
    {
        $return = [
            'exists' => false,
            'has_username' => false
        ];

        $user = UserRepository::init()
            ->firstRegisteredByPhoneNumber($request->phone_code, $request->phone_number);

        if ( $user ) {
            $return['exists'] = true;
            $return['has_username'] = ($user->nickname) ? true : false;
        }

        /** @TODO: Refactore test case */
        if ($request->phone_code == '371' && $request->phone_number == '00000000') {
            UserPhoneConfirm::createTestPhoneConfirm($request->phone_code, $request->phone_number);

            return jsonSuccess($return);
        }

        $this->verificationCodeService
            ->startVerify($request->phone_code, $request->phone_number);

        return jsonSuccess($return);
    }

    /**
     * @param PhoneCodeRequest $phoneCodeRequest
     * @param TokenManager $tokenManager
     *
     * @return JsonResponse
     */
    public function verifyPhoneCodeAndRegister(PhoneCodeRequest $phoneCodeRequest, TokenManager $tokenManager)
    {
        try {
            $phoneConfirm = $this->verificationCodeService
                ->completeVerify($phoneCodeRequest->code);
        } catch (RecordNotExistsException $e) {
            return jsonErrorMessage($e->getMessage());
        }

        $phoneHash = phoneHash($phoneConfirm->phone_code, $phoneConfirm->phone_number);
        $user = User::repository()->firstByPhoneHash($phoneHash);

        if ($user && $user->is_registered) {
            return jsonErrorMessage('Phone number already exists');
        }

        if (!$user) {
            $user = UserEntityManager::createUser(
                $phoneConfirm->phone_code,
                $phoneConfirm->phone_number
            );
        }

        if (!$user->is_registered) {
            $user->makeRegistered($phoneConfirm->phone_code, $phoneConfirm->phone_number);

            DemoUserManager::makeFriend($user);
            DemoUserManager::createPrivateCapsule($user);
        }

        $token = $tokenManager->generateToken($user);

        return jsonSuccess([
            'token' => $token->access_token,
        ]);
    }

    /**
     * @param PhoneCodeRequest $phoneCodeRequest
     * @param TokenManager $tokenManager
     *
     * @return JsonResponse
     */
    public function login(PhoneCodeRequest $phoneCodeRequest, TokenManager $tokenManager)
    {
        try {
            $phoneConfirm = $this->verificationCodeService
                ->completeVerify($phoneCodeRequest->code);

        } catch (RecordNotExistsException $e) {
            return jsonErrorMessage($e->getMessage());
        }

        $phoneHash = phoneHash($phoneConfirm->phone_code, $phoneConfirm->phone_number);
        $user = UserRepository::init()->firstByPhoneHash($phoneHash);

        $new_user = false;
        $has_username = false;

        if (!$user) {
            $user = UserEntityManager::createUser(
                $phoneConfirm->phone_code,
                $phoneConfirm->phone_number
            );

            $new_user = true;

            DemoUserManager::makeFriend($user);
            DemoUserManager::createPrivateCapsule($user);
        }

        if (!$user->is_registered) {
            $user->makeRegistered($phoneConfirm->phone_code, $phoneConfirm->phone_number);

            $new_user = true;

            DemoUserManager::makeFriend($user);
            DemoUserManager::createPrivateCapsule($user);
        }

        if ( $user->nickname ) $has_username = true;

        $token = $tokenManager->generateToken($user);

        return jsonSuccess([
            'onboarding_done' => (bool)$user->is_on_boarding_done,
            'token' => $token->access_token,
            'is_new' => $new_user,
            'has_username' => $has_username
        ]);
    }
}
