<?php
require_once 'ABaseTest.php';

class PAKDashboardTest extends BaseTest
{
    protected $token;
    protected $userId;

    const USERNAME_USERDINAS    = 'pak.dinas.kota.depok';
    const PASSWORD_USERDINAS    = 'password12345';
    const INSTANSIID_USERDINAS  = 542;

    const URL_LIST_REGULASI     = 'pak/dashboard/list-regulasi';
    const URL_LIST_ISIANSEKOLAH = 'pak/isiansekolah/index';
    const URL_STAT_IMPLEMENTASI = 'pak/dashboard/stats-implementasi';

    const LIMIT = 1000;
    const OFFSET = 0;

    public function setUp()
    {
        parent::setUp();
        $loginInfo = $this->doLogin();
        $this->token = $loginInfo['token'];
        $this->userId = $loginInfo['user_id'];
    }

    protected function doLogin()
    {
        $login = $this->login(getenv("TEST_ADMIN_USERNAME"), getenv("TEST_ADMIN_PASSWORD"));
        $this->assertContains(
            [
                'success' => true
            ],
            $login
        );
        return $login['data'];
    }

    protected function doLoginUserDinas()
    {
        $login = $this->login(self::USERNAME_USERDINAS, self::PASSWORD_USERDINAS);
        $this->assertContains(
            [
                'success' => true
            ],
            $login
        );
        return $login['data'];
    }

    protected function getAuthorization(): array
    {
        return ['Authorization' => 'Bearer ' . $this->token];
    }

    #region LIST REGULASI
    public function testListRegulasiShouldGiveInvalidAuth() {
        $this->doAPIShouldGiveSubsetResponse(
            'GET',
            self::URL_LIST_REGULASI,
            465,
            [
                'success' => false,
                'message' => 'Invalid Authentication'
            ],
            "\npak/dashboard/list-regulasi testListRegulasiShouldGiveInvalidAuth passed"
        );
    }

    public function testListRegulasiShouldGiveSuccessResponse() {
        $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'headers' => $this->getAuthorization()
            ],
            200,
            "pak/dashboard/list-regulasi testListRegulasiShouldGiveSuccessResponse passed"
        );
    }

    public function testListRegulasiWFilterTahun() {
        $tahun = 2020;
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'query' => [
                    'tahun' => $tahun,
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ],
                'headers' => $this->getAuthorization()
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertEquals($tahun, $row['tahun']);
        }

        self::$messages = array_merge(self::$messages, ['pak/dashboard/list-regulasi testListRegulasiWFilterTahun ' . $tahun . ' passed']);
    }

    public function testListRegulasiWithFilterKeywordTentang() {
        $keyword = 'peraturan';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'query' => [
                    'keyword' => $keyword,
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ],
                'headers' => $this->getAuthorization()
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertStringContainsStringIgnoringCase($keyword, $row['tentang']);
        }

        self::$messages = array_merge(self::$messages, ['pak/dashboard/list-regulasi testListRegulasiWFilterKeywordTentang ' . $keyword . ' passed']);
    }

    public function testListRegulasiWithFilterKeywordNomor() {
        $keyword = '16';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'query' => [
                    'keyword' => $keyword,
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ],
                'headers' => $this->getAuthorization()
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertStringContainsStringIgnoringCase($keyword, $row['nomor']);
        }

        self::$messages = array_merge(self::$messages, ['pak/dashboard/list-regulasi testListRegulasiWFilterKeywordNomor ' . $keyword . ' passed']);
    }

    public function testListRegulasiWithFilterKeywordJenisDokumen() {
        $keyword = 'Peraturan';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'query' => [
                    'keyword' => $keyword,
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ],
                'headers' => $this->getAuthorization()
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertStringContainsStringIgnoringCase($keyword, $row['jenis_dokumen']);
        }

        self::$messages = array_merge(self::$messages, ['pak/dashboard/list-regulasi testListRegulasiWithFilterKeywordJenisDokumen ' . $keyword . ' passed']);
    }

    public function testListRegulasiWithFilterKeywordNamaInstansi() {
        $keyword = 'depok';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'query' => [
                    'keyword' => $keyword,
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ],
                'headers' => $this->getAuthorization()
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertStringContainsStringIgnoringCase($keyword, $row['nama_instansi']);
        }

        self::$messages = array_merge(self::$messages, ['pak/dashboard/list-regulasi testListRegulasiWithFilterKeywordNamaInstansi ' . $keyword . ' passed']);
    }

    public function testListRegulasiUserDinas()
    {
        $token = $this->doLoginUserDinas()['token'];
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_REGULASI,
            [
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ],
                'headers' => ['Authorization' => 'Bearer ' . $token]
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertEquals(self::INSTANSIID_USERDINAS, $row['id_instansi']);
        }

        self::$messages = array_merge(self::$messages, ['pak/dashboard/list-regulasi testListRegulasiUserDinas ' . self::USERNAME_USERDINAS . ' passed']);
    }
    #endregion

    #region LIST ISIANSEKOLAH
    public function testListIsiansekolahShouldGiveInvalidAuth() {
        $this->doAPIShouldGiveSubsetResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            465,
            [
                'success' => false,
                'message' => 'Invalid Authentication'
            ],
            "\n" . self::URL_LIST_ISIANSEKOLAH . " testListIsiansekolahShouldGiveInvalidAuth passed"
        );
    }

    public function testListIsiansekolahShouldGiveSuccessResponse() {
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET
                ]
            ],
            200,
            ''
        )['data']['result'];

        foreach ($rows as $row) {
            $this->assertArrayHasKey('id', $row);
            $this->assertArrayHasKey('sekolah', $row);
            $this->assertArrayHasKey('metode', $row);
            $this->assertArrayHasKey('detail', $row);

            $details = $row['detail'];
            foreach ($details as $detail) {
                $this->assertArrayHasKey('id', $detail);
                $this->assertArrayHasKey('metode_id', $detail);
                $this->assertArrayHasKey('documents', $detail);
                $this->assertArrayHasKey('images', $detail);
            }
        }

        self::$messages = array_merge(self::$messages, [self::URL_LIST_ISIANSEKOLAH . " testListIsiansekolahShouldGiveSuccessResponse passed"]);
    }

    public function testListIsiansekolahWFilterKeyword() {
        $keyword = 'SD ALAM KEBUN';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET,
                    'keyword' => $keyword
                ]
            ],
            200,
            ''
        )['data']['result'];
        $this->assertValuesStringContainsStringIgnoringCaseByKey($rows, $keyword, ['sekolah', 'nama'], self::URL_LIST_ISIANSEKOLAH . ' testListIsiansekolahWFilterKeyword ' . $keyword . ' passed');
    }

    public function testListIsiansekolahWFilterStatus()
    {
        $mapStatus = [
            1 => 'Draft',
            2 => 'Submitted',
            3 => 'Verified',
            4 => 'Returned'
        ];
        $status = 3;
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET,
                    'status' => $status
                ]
            ],
            200,
            ''
        )['data']['result'];
        $this->assertValuesStringContainsStringIgnoringCaseByKey($rows, $mapStatus[$status], 'status', self::URL_LIST_ISIANSEKOLAH . ' testListIsiansekolahWFilterStatus ' . $status . '(' . $mapStatus[$status] . ')' . ' passed');
    }

    public function testListIsiansekolahWFilterTahunAjaran()
    {
        $tahunAjaran = '2020-2021';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET,
                    'tahun_ajaran' => $tahunAjaran
                ]
            ],
            200,
            ''
        )['data']['result'];
        $this->assertValuesStringContainsStringIgnoringCaseByKey($rows, $tahunAjaran, 'tahun_ajaran', self::URL_LIST_ISIANSEKOLAH . ' testListIsiansekolahWFilterTahunAjaran ' . $tahunAjaran . ' passed');
    }

    public function testListIsiansekolahWFilterProvinsi()
    {
        $provinsi = 'sumatera';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET,
                    'provinsi' => $provinsi
                ]
            ],
            200,
            ''
        )['data']['result'];
        $this->assertValuesStringContainsStringIgnoringCaseByKey($rows, $provinsi, ['sekolah', 'provinsi'], self::URL_LIST_ISIANSEKOLAH . ' testListIsiansekolahWFilterProvinsi ' . $provinsi . ' passed');
    }

    public function testListIsiansekolahWFilterKota()
    {
        $kota = 'depok';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET,
                    'kota_kab' => $kota
                ]
            ],
            200,
            ''
        )['data']['result'];
        $this->assertValuesStringContainsStringIgnoringCaseByKey($rows, $kota, ['sekolah', 'kota_kab'], self::URL_LIST_ISIANSEKOLAH . ' testListIsiansekolahWFilterKota ' . $kota . ' passed');
    }

    public function testListIsiansekolahWFilterJenjang()
    {
        $jenjang = 'sd';
        $rows = $this->doAPIShouldGiveSuccessResponse(
            'GET',
            self::URL_LIST_ISIANSEKOLAH,
            [
                'headers' => $this->getAuthorization(),
                'query' => [
                    'limit' => self::LIMIT,
                    'offset' => self::OFFSET,
                    'jenjang' => $jenjang
                ]
            ],
            200,
            ''
        )['data']['result'];
        $this->assertValuesStringContainsStringIgnoringCaseByKey($rows, $jenjang, ['sekolah', 'jenjang', 'nama_jenjang'], self::URL_LIST_ISIANSEKOLAH . ' testListIsiansekolahWFilterJenjang ' . $jenjang . ' passed');
    }
    #endregion

    #region STAT IMPLEMENTASI
    public function testStatImplementasiShouldGiveInvalidAuth() {
        $this->doAPIShouldGiveSubsetResponse(
            'GET',
            self::URL_STAT_IMPLEMENTASI,
            465,
            [
                'success' => false,
                'message' => 'Invalid Authentication'
            ],
            "\n" . self::URL_STAT_IMPLEMENTASI . " testStatImplementasiShouldGiveInvalidAuth passed"
        );
    }

    public function testStatImplementasiShouldGiveSuccessResponse() {
        $result = $this->doAPIShouldGiveSubsetResponse(
            'GET',
            self::URL_STAT_IMPLEMENTASI,
            200,
            [
                'success' => true
            ],
            '',
            [
                'headers' => $this->getAuthorization()
            ]
        )['data'];

        $this->assertArrayHasKey('persentase', $result);
        $this->assertArrayHasKey('nominal', $result);

        $this->assertArrayHasKey('sudah_menerapkan', $result['persentase']);
        $this->assertIsNumeric($result['persentase']['sudah_menerapkan']);
        $this->assertArrayHasKey('belum_menerapkan', $result['persentase']);
        $this->assertIsNumeric($result['persentase']['belum_menerapkan']);

        $this->assertArrayHasKey('sudah_menerapkan', $result['nominal']);
        $this->assertIsNumeric($result['nominal']['sudah_menerapkan']);
        $this->assertArrayHasKey('belum_menerapkan', $result['nominal']);
        $this->assertIsNumeric($result['nominal']['belum_menerapkan']);

        self::$messages = array_merge(self::$messages, [self::URL_STAT_IMPLEMENTASI . " testStatImplementasiShouldGiveSuccessResponse passed"]);
    }
    #endregion

    #region ASSERTION
    private function assertValuesStringContainsStringIgnoringCaseByKey($rows, $expected, $key, $successMessage = '') {
        foreach ($rows as $row) {
            if (is_array($key)) {
                $idx = 0;
                $current = $row[$key[$idx]];
                foreach ($key as $k) {
                    if ($idx > 0) {
                        $current = $current[$k];
                    }
                    $idx++;
                }
                $this->assertStringContainsStringIgnoringCase($expected, $current);
            } else {
                $this->assertStringContainsStringIgnoringCase($expected, $row[$key]);
            }
        }

        self::$messages = array_merge(self::$messages, [$successMessage]);
    }
    #endregion
}

