<?php
namespace Backend\BaseBundle\Tests\Controller\Backend;

use Backend\BaseBundle\Model\SiteUser;
use Backend\BaseBundle\Model\SiteUserQuery;
use Backend\BaseBundle\Tests\Fixture\BackendWebTestCase;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Serializer\Tests\Model;

/**
 * @group functional
 */
class SecurityControllerTest extends BackendWebTestCase
{
    public function test_LoginAction()
    {
        //arrange
        //act
        $this->client->request('GET', $this->generateUrl('@BackendLogin', array('slug' => 'dgfactor')));
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isOk());
    }

    public function test_LoginCheck()
    {
        //arrage
        $csrfToken = 'top_secret_token';
        $slug = 'dgfactor';
        $username = 'admin_dgfactor';
        $password = '12345';
        $redirectPath = $this->generateUrl('backend_base_backend_default_index', array('slug' => $slug), UrlGenerator::ABSOLUTE_URL);

        $userProvider = $this->client->getContainer()->get('site_user_provider');
        $userManager =  $this->client->getContainer()->get('site_user_manager');
        $userProvider->setSlug($slug);
        $user = $userProvider->loadUserByUsernameOrEmail($username);
        $user->setPlainPassword($password);
        $userManager->updateUser($user);
        $this->session->set('_csrf/authenticate', $csrfToken);
        $this->session->set('_security.site_backend.target_path', $redirectPath);
        $this->writeServerSession();

        //act
        $this->client->request('POST', $this->generateUrl('@BackendLoginCheck', array('slug' => $slug)), array(
            '_username' => $username,
            '_password' => $password,
            '_csrf_token' => $csrfToken,
        ));
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isRedirect($redirectPath));
    }

    public function test_access_ok()
    {
        //arrange
        $slug = 'dgfactor';
        $username = 'admin_dgfactor';

        $userProvider = $this->client->getContainer()->get('site_user_provider');
        $userProvider->setSlug($slug);
        $user = $userProvider->loadUserByUsernameOrEmail($username);
        $this->loginWithRoles($user, array('ROLE_SUPERADMIN'));

        //act
        $this->client->request('GET', $this->generateUrl('backend_base_backend_default_index', array('slug' => $slug)));
        $response = $this->client->getResponse();

        //arrange
        $this->assertTrue($response->isOk());
    }

    public function test_access_bad_slug()
    {
        //arrange
        $slug = 'dgfactor';
        $username = 'admin_dgfactor';

        $userProvider = $this->client->getContainer()->get('site_user_provider');
        $userProvider->setSlug($slug);
        $user = $userProvider->loadUserByUsernameOrEmail($username);
        $this->loginWithRoles($user, array('ROLE_SUPERADMIN'));

        //act
        $this->client->request('GET', $this->generateUrl('backend_base_backend_default_index', array('slug' => 'badsite')));
        $response = $this->client->getResponse();

        //arrange
        $this->assertFalse($response->isOk());
    }

    public function test_require_login()
    {
        $slug = 'dgfactor';
        $username = 'admin_dgfactor';
        $redirectPath = $this->generateUrl('@BackendLogin', array('slug' => $slug), UrlGenerator::ABSOLUTE_URL);

        $userProvider = $this->client->getContainer()->get('site_user_provider');
        $userProvider->setSlug($slug);
        $user = $userProvider->loadUserByUsernameOrEmail($username);

        //act
        $this->client->request('GET', $this->generateUrl('backend_base_backend_default_index', array('slug' => $slug)));
        $response = $this->client->getResponse();

        //arrange
        $this->assertTrue($response->isRedirect($redirectPath));
    }

    public function test_forgetPasswordPOSTAction_emailNotFound()
    {
        //arrange
        $slug = 'dgfactor';
        $email = '123@dgfactor.com';
        $redirectPath = $this->generateUrl('@BackendForgetPassword', array('slug' => $slug));

        //act
        $this->client->request(
            'POST',
            $this->generateUrl('backend_base_backend_security_forgetpasswordpost', array('slug' => $slug), UrlGenerator::ABSOLUTE_URL),
            array(
                'email' => $email,
                'g-recaptcha-response' => '',
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isRedirect($redirectPath));

    }

    public function test_forgetPasswordPOSTAction_badEmail()
    {
        //arrange
        $slug = 'dgfactor';
        $email = '123dgfac';
        $redirectPath = $this->generateUrl('@BackendForgetPassword', array('slug' => $slug));

        //act
        $this->client->request(
            'POST',
            $this->generateUrl('backend_base_backend_security_forgetpasswordpost', array('slug' => $slug), UrlGenerator::ABSOLUTE_URL),
            array(
                'email' => $email,
                'g-recaptcha-response' => '',
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isRedirect($redirectPath));

    }

    public function test_forgetPasswordPOSTAction_validEmail()
    {
        //arrange
        $slug = 'dgfactor';
        $email = 'admin_dgfactor@dgfactor.com';
        $loginName = 'admin_dgfactor';
        $mailSubject = '忘記密碼確認信';
        $redirectPath = $this->generateUrl('@BackendLogin', array('slug' => $slug));

        //act
        $this->client->request(
            'POST',
            $this->generateUrl('backend_base_backend_security_forgetpasswordpost', array('slug' => $slug), UrlGenerator::ABSOLUTE_URL),
            array(
                'email' => $email,
                'g-recaptcha-response' => '',
            )
        );
        $response = $this->client->getResponse();
        $mailCollector = $this->client->getProfile()->getCollector('swiftmailer');
        $to = $mailCollector->getMessages('site')[0]->getTo();
        
        $mailSubjectResult = $mailCollector->getMessages('site')[0]->getSubject();
        //$mailContent = $mailCollector->getMessages('site')[0]->getBody();

        //assert
        $this->assertEquals(array(
            $email => $loginName,
        ), $to);
        $this->assertTrue($response->isRedirect($redirectPath));
        $this->assertEquals($mailSubject, $mailSubjectResult);
    }

    public function test_forgetPasswordCheckTokenAction_invalidEmail()
    {
        //arrange
        $slug = 'dgfactor';
        $email = '12314@dgfactor.com';
        $token = 'hjhgkjghkjg';

        //act
        $this->client->request(
            'GET',
            $this->generateUrl(
                'backend_base_backend_security_forgetpasswordchecktoken',
                array(
                    'slug' => $slug,
                    'token' => $token,
                    'email' => $email,
                )
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isNotFound());
    }

    public function test_forgetPasswordCheckTokenAction_invalidToken()
    {
        //arrange
        $slug = 'dgfactor';
        $email = 'admin_dgfactor@dgfactor.com';
        $token = 'hjhgkjghkjg';

        //act
        $this->client->request(
            'GET',
            $this->generateUrl(
                'backend_base_backend_security_forgetpasswordchecktoken',
                array(
                    'slug' => $slug,
                    'token' => $token,
                    'email' => $email,
                )
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isNotFound());
    }

    public function test_forgetPasswordCheckTokenAction_tokenExpired()
    {
        //arrange
        $slug = 'dgfactor';
        $email = 'admin_dgfactor@dgfactor.com';
        $user = SiteUserQuery::create()
            ->filterByEmail($email)
            ->useSiteQuery()
                ->filterBySlug($slug)
            ->endUse()
            ->findOne();

        /** @var SiteUser $user */
        $user->generateToken();
        $user->setTokenExpiredAt(time());
        $user->save();

        //act
        $this->client->request(
            'GET',
            $this->generateUrl(
                'backend_base_backend_security_forgetpasswordchecktoken',
                array(
                    'slug' => $slug,
                    'token' => $user->getConfirmToken(),
                    'email' => $email,
                )
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isNotFound());
    }

    public function test_forgetPasswordCheckTokenAction_valid()
    {
        //arrange
        $slug = 'dgfactor';
        $email = 'admin_dgfactor@dgfactor.com';
        $redirectPath = $this->generateUrl('backend_base_backend_security_resetpassword', array('slug' => $slug));
        $user = SiteUserQuery::create()
            ->filterByEmail($email)
            ->useSiteQuery()
            ->filterBySlug($slug)
            ->endUse()
            ->findOne();

        /** @var SiteUser $user */
        $user->generateToken();
        $user->save();

        //act
        $this->client->request(
            'GET',
            $this->generateUrl(
                'backend_base_backend_security_forgetpasswordchecktoken',
                array(
                    'slug' => $slug,
                    'token' => $user->getConfirmToken(),
                    'email' => $email,
                )
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isRedirect($redirectPath));
    }

    public function test_resetPasswordAction_invalidSession()
    {
        //arrange
        $slug = 'dgfactor';
        $redirectPath = $this->generateUrl('backend_base_backend_security_resetpassword', array('slug' => $slug));


        //act
        $this->client->request(
            'GET',
            $this->generateUrl(
                'backend_base_backend_security_resetpassword',
                array(
                    'slug' => $slug,
                )
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isNotFound());
    }

    public function test_resetPasswordAction_valid()
    {
        //arrange
        $slug = 'dgfactor';
        $email = 'admin_dgfactor@dgfactor.com';
        $user = SiteUserQuery::create()
            ->filterByEmail($email)
            ->useSiteQuery()
                ->filterBySlug($slug)
            ->endUse()
            ->findOne();
        $this->session->set('resetpassworduser', $user);
        $this->writeServerSession();

        //act
        $this->client->request(
            'GET',
            $this->generateUrl(
                'backend_base_backend_security_resetpassword',
                array(
                    'slug' => $slug,
                )
            )
        );
        $response = $this->client->getResponse();

        //assert
        $this->assertTrue($response->isOk());
    }
}