<?php

class LoginTest extends \PHPUnit\Framework\TestCase {
    public function setUp(): void {
        global $CONF;

        $this->cleanUp();

        $CONF['pacrypt'] = 'md5'; // crap

        db_execute("INSERT INTO domain(domain, description, transport) values ('example.com', 'test', 'foo')", [], true);

        db_execute(
            "INSERT INTO mailbox(username, password, name, maildir, local_part, domain) VALUES(:username, :password, :name, :maildir, :local_part, :domain)",
            [
                'username' => 'test@example.com',
                'password' => pacrypt('foobar'),
                'name' => 'test user',
                'maildir' => '/foo/bar',
                'local_part' => 'test',
                'domain' => 'example.com',
            ]);


        parent::setUp();
    }


    public function tearDown(): void {
        $this->cleanUp();
        parent::tearDown(); // TODO: Change the autogenerated stub
    }

    private function cleanUp() {
        db_query('DELETE FROM alias');
        db_query('DELETE FROM alias_domain');
        db_query('DELETE FROM mailbox');
        db_query('DELETE FROM domain_admins');
        db_query('DELETE FROM domain');
    }

    public function testPasswordchange() {
        $login = new Login('mailbox');

        $this->assertTrue($login->login('test@example.com', 'foobar'));

        // Can't change - current password wrong.
        try {
            $login->changePassword('test@example.com', 'foobar2', 'foobar2');
            $this->fail("Exception should have been thrown");
        } catch (\Exception $e) {
            $this->assertEquals("You didn't supply your current password!", $e->getMessage());
        }


        // Should change, current password correct.
        $this->assertTrue($login->changePassword('test@example.com', 'foobar2', 'foobar'));

        // Can't now login with the old password
        $this->assertFalse($login->login('test@example.com', 'foobar'));

        // Can login with the new one...
        $this->assertTrue($login->login('test@example.com', 'foobar2'));
    }


    public function testInvalidUsers() {
        $login = new Login('mailbox');

        $this->assertFalse($login->login('test', 'password'));
        $this->assertFalse($login->login('test', ''));
        $this->assertFalse($login->login('', ''));
    }


    public function testEmptyStringWithDovecot() {
        global $CONF;

        if (!file_exists('/usr/bin/doveadm')) {
            $this->markTestSkipped("/usr/bin/doveadm doesn't exist.");
        }

        $CONF['encrypt'] = 'dovecot:sha512';


        db_execute(
            "UPDATE mailbox SET password = :password WHERE username = :username",
            [
                'username' => 'test@example.com',
                'password' => '{SHA512}ClAmHr0aOQ/tK/Mm8mc8FFWCpjQtUjIElz0CGTN/gWFqgGmwElh89WNfaSXxtWw2AjDBmyc1AO4BPgMGAb8kJQ==', // pacrypt('foobar'),
            ]
        );

        $l = new Login('mailbox');
        $this->assertFalse($l->login('test@example.com', ''));

        $this->assertTrue($l->login('test@example.com', 'foobar'));

        $this->assertFalse($l->login('test@fails.com', 'foobar'));
    }

    public function testValidLogin() {
        $login = new Login('mailbox');

        $this->assertFalse($login->login('test', 'password'));
        $this->assertFalse($login->login('test', 'foobar'));
        $this->assertFalse($login->login('', ''));
    }

    public function testPasswordRecovery() {
        $login = new Login('mailbox');
        $this->assertFalse($login->generatePasswordRecoveryCode(''));
        $this->assertFalse($login->generatePasswordRecoveryCode('doesnotexist'));
        $this->assertNotEmpty($login->generatePasswordRecoveryCode('test@example.com'));
    }
}
