<?php
class SekolahNewClient extends BackgroundBaseClient
{
    private $token;
    private $jenjangLookup;

    public function filterResponse($body, $result)
    {
        parent::filterResponse($body, $result);
        if ($this->logger != null) {
            if($result != null) {
                if(!is_array($result)) {
                    $this->logger->addItem("api_result_code", -1);
                    $this->logger->addItem("api_result_message", $result);
                }
                else if(array_key_exists('Message', $result)) {
                    $this->logger->addItem("api_result_code", -1);
                    $this->logger->addItem("api_result_message", $result['Message']);
                }
            }
        }
    }

    private function getHeader() {
        return [
            "Authorization" => "Basic " . base64_encode($this->prop["username"] . ':' . $this->prop["password"])
        ];
    }

    public function gtk($npsn)
    {
        $method = "GET";
        $path = "/api/kpk/guru";
        $params = [
            "query" => [
                "npsn" => $npsn
            ],
            "headers" => $this->getHeader()
        ];

        //region LOG Definition
        $this->setApiName("SekolahNew-gtk");
        //endregion

        return $this->execute($method, $path, $params, false);
    }

    public function getToken()
    {
        $method = "POST";
        $path = "/api/kpk/login";
        $params = [
            "headers" => [
                "Content-Type" => "application/x-www-form-urlencoded"
            ],
            "form_params" => [
                "username" => $this->prop["username"],
                "password" => $this->prop["password"],
                "grant_type" => $this->prop["grant_type"]
            ]
        ];

        //region LOG Definition
        $this->setApiName("SekolahNew-get_token");
        $this->setLogParams($params['form_params']);
        //endregion

        $res = $this->execute($method, $path, $params);
        $this->token = $res["token"];
    }

    public function initializeJenjangLookup()
    {
        $lookup = [];
        $jenjang_list = Jenjang::find()->toArray();

        foreach ($jenjang_list as $key => $jenjang) {
            $lookup[strtolower($jenjang['nama_jenjang'])] = $jenjang['id'];
        }

        $this->jenjangLookup = $lookup;
    }

    public function getAndRegisterJenjangId($input)
    {
        $bentuk = trim($input);
        if (empty($bentuk)) {
            return null;
        }

        $key = strtolower($bentuk);

        $result = array_key_exists($key, $this->jenjangLookup) ? $this->jenjangLookup[$key] : null;

        if (empty($result)) {
            $newJenjang = new Jenjang();
            $newJenjang->nama_jenjang = $bentuk;
            $newJenjang->save();

            $result = (int)$newJenjang->id;
            $this->jenjangLookup[$key] = $newJenjang->id;
        }

        return $result;
    }

    public function getSekolah($npsn)
    {
        $method = 'GET';
        $path = '/api/kpk/sekolah';
        $params = [
            "query" => [
                "npsn" => $npsn
            ],
            "headers" => $this->getHeader()
        ];

        //region LOG Definition
        $this->setApiName("SekolahNew-get_sekolah");
        //endregion

        $res = $this->execute($method, $path, $params, false);
        return $res;
    }

    public function updateForYear($ym, $debug = false) {
        $limit = 201801;
        if ($ym >= $limit) {
            $str = strval($ym);
            $year = substr($str, 0, 4);
            $month = substr($str, 4, 2);
            $startDate = date("Y-m-d", strtotime($year . '-' . $month . '-' . '01'));
            $endDate = date("Y-m-t", strtotime($year . '-' . $month . '-' . '01'));
            $params = [
                "query" => [
                    "startdate" => $startDate,
                    "enddate" => $endDate
                ]
            ];
            $this->retryRequestSekolah($debug);
            $this->requestSekolah($params, $debug);
        } else {
            echo "Wrong first argument. Year must be greater than " . $limit;
        }
    }

    public function updateDaily($debug = false)
    {
        $params = [
            "query" => [
                "startdate" => date('Y-m-d', strtotime('-1 day')),
                "enddate" => date('Y-m-d')
            ]
        ];
        $this->retryRequestSekolah($debug);
        $this->requestSekolah($params, $debug);
    }

    public function init($debug = false)
    {
        $sdate = strtotime('01-01-2018');
        $now = strtotime('today');

        while ($sdate < $now) {
            $edate = strtotime('1 day', $sdate);
            $startdate = date('Ymd', $sdate);
            $enddate = date('Ymd', $edate);
            $params = [
                "query" => [
                    "startdate" => $startdate,
                    "enddate" => $enddate
                ]
            ];
            if ($debug) {
                echo "================================================================\n";
                echo "update sekolah dari tanggal " . date('Y-m-d', $sdate) . " sampai tanggal " . date('Y-m-d', $edate) . "\n";
            }
            $this->requestSekolah($params, $debug);
            $sdate = $edate;
        }
    }

    public function getUpdateSekolah($startdate, $enddate)
    {
        $method = 'GET';
        $path = '/api/kpk/update-sekolah';
        $params = [
            "headers" => $this->getHeader(),
            "query" => [
                "startdate" => $startdate,
                "enddate" => $enddate
            ]
        ];
        return $this->execute($method, $path, $params);
    }

    private function retryRequestSekolah($debug = false)
    {
        $this->initializeJenjangLookup();
        $data = LogSekolahErrors::find('error_count <= ' . getenv('MAX_RETRY_SEKOLAH_ERROR'));
        if ($debug) {
            echo "total data dari LogSekolahErors: " . count($data) . "\n";
            echo "================================================================\n";
        }
        if (count($data) > 0) {
            foreach ($data as $logSekolahErrors) {
                $logSekolah = LogSekolahErrors::findFirst("id = " . $logSekolahErrors->id);
                try {
                    $sekolah = $this->getSekolah($logSekolahErrors->npsn);
                    if (!is_array($sekolah)) {
                        // update log_sekolah_errors
                        $logSekolah->error_count = $logSekolah->error_count + 1;
                        $logSekolah->last_error_at = date('Y-m-d H:i:s');
                        $logSekolah->last_error_message = (is_string($sekolah) ? $sekolah : 'Format response tidak diketahui');
                        $logSekolah->save();
                        continue;
                    }

                    $sekolahModel = Sekolah::findFirst(
                        [
                            "npsn = :npsn:",
                            "bind" => [
                                "npsn" => $logSekolahErrors->npsn
                            ]
                        ]
                    );

                    if (!$sekolahModel) {
                        $sekolahModel = new Sekolah();
                    } else {
                        if ($sekolahModel->tanggal_update_sekolah == $sekolah["tanggal_update_sekolah"]) {
                            $logSekolah->delete();
                            continue;
                        }
                    }
                    $this->updateSekolah($sekolahModel, $sekolah);
                    $logSekolah->delete();
                } catch (\Exception $e) {
                    // update log_sekolah_errors
                    $logSekolah->error_count = $logSekolah->error_count + 1;
                    $logSekolah->last_error_at = date('Y-m-d H:i:s');
                    $logSekolah->last_error_message = $e->getMessage();
                    $logSekolah->save();
                }
            }
        }
    }

    private function requestSekolah($params, $debug = false)
    {
        $this->startTime = microtime(true);
        $this->initializeJenjangLookup();
        if ($debug) print_r($this->jenjangLookup);

        $method = 'GET';
        $path = '/api/kpk/update-sekolah';
        $params["headers"] = $this->getHeader();

        //region LOG Definition
        $this->setApiName("SekolahNew-request_sekolah");
        //endregion

        $res = $this->execute($method, $path, $params);
        $this->objectsProcessed = 0;
        if ($debug) {
            echo "total data dari kemdikbud: " . (is_array($res) ? count($res) : 0) . "\n";
            echo "================================================================\n";
        }
        if(is_array($res)) {
            foreach ($res as $update) {
                if (!array_key_exists('soft_delete', $update) || $update['soft_delete'] == '0') {
                    try {
                        $sekolah = $this->getSekolah($update["npsn"]);
                        if (!is_array($sekolah)) {
                            if ($debug) echo "data sekolah npsn:" . $update["npsn"] . " " . $sekolah . " \n";

                            // insert log_sekolah_errors
                            $logSekolah = new LogSekolahErrors();
                            $logSekolah->npsn = $update['npsn'];
                            $logSekolah->error_count = 1;
                            $logSekolah->last_error_message = (is_string($sekolah) ? $sekolah : 'Format response tidak diketahui');
                            $logSekolah->save();

                            continue;
                        }

                        $sekolahModel = Sekolah::findFirst(
                            [
                                "npsn = :npsn:",
                                "bind" => [
                                    "npsn" => $update["npsn"]
                                ]
                            ]
                        );

                        if (!$sekolahModel) {
                            if ($debug) echo "sekolah baru " . $sekolah["sekolah"] . "\n";
                            $sekolahModel = new Sekolah();
                        } else {
                            if ($sekolahModel->tanggal_update_sekolah == $sekolah["tanggal_update_sekolah"]) {
                                if ($debug) echo "data sekolah " . $sekolah["sekolah"] . " sudah up to date\n";
                                continue;
                            }
                            if ($debug) echo "update sekolah " . $sekolah["sekolah"] . "\n";
                        }
                        $this->updateSekolah($sekolahModel, $sekolah);
                        $this->objectsProcessed++;
                    } catch (\Exception $e) {
                        if ($debug) {
                            echo "error sekolah npsn " . $update["npsn"];
                            echo $e->getMessage() . "\n";
                        }

                        // insert into log_sekolah_errors
                        $logSekolah = new LogSekolahErrors();
                        $logSekolah->npsn = $update['npsn'];
                        $logSekolah->error_count = 1;
                        $logSekolah->last_error_message = $e->getMessage();
                        $logSekolah->save();
                    }
                } elseif (array_key_exists('soft_delete', $update) && $update['soft_delete'] == '1') {
                    $sekolahModel = Sekolah::findFirst(
                        [
                            "npsn = :npsn:",
                            "bind" => [
                                "npsn" => $update["npsn"]
                            ]
                        ]
                    );
                    if ($sekolahModel) {
                        $sekolahModel->deleted_at = date('Y-m-d H:i:s');
                        $sekolahModel->save();
                    }
                }
            }
        }
        $this->endTime = microtime(true);
    }

    public function updateSekolah($des, $src)
    {
        $des->akreditasi = $src["akreditasi"];
        $des->akses_internet = $src["internet"];
        $des->alamat = $src["alamat_jalan"];
        $des->bentuk = $src["bentuk_pendidikan"];
        $des->bentuk_pendidikan = $src["bentuk_pendidikan"];
//        $des->data_kosong = $src["data_kosong"];
        $des->email = trim($src["email"]);
        $des->guru_31_35_th = $src["guru_31_35_th"];
        $des->guru_36_40_th = $src["guru_36_40_th"];
        $des->guru_41_45_th = $src["guru_41_45_th"];
        $des->guru_46_50_th = $src["guru_46_50_th"];
        $des->guru_51_55_th = $src["guru_51_55_th"];
        $des->guru_belums1 = $src["guru_kurang_s1"];
        $des->guru_belumsertifikasi = $src["guru_belum_sertifikasi"];
        $des->guru_gol1 = $src["guru_gol_1"];
        $des->guru_gol2 = $src["guru_gol_2"];
        $des->guru_gol3 = $src["guru_gol_3"];
        $des->guru_gol4 = $src["guru_gol_4"];
        $des->guru_gtt = $src["guru_gtt"];
        $des->guru_gty = $src["guru_gty"];
        $des->guru_honor = $src["guru_honor"];
        $des->guru_kurang_30_th = $src["guru_kurang_30_th"];
        $des->guru_laki = $src["guru_l"];
        $des->guru_lebih_55_th = $src["guru_lebih_55_th"];
        $des->guru_perempuan = $src["guru_p"];
        $des->guru_pns = $src["guru_pns"];
        $des->guru_s1lebih = $src["guru_s1_lebih"];
        $des->guru_sertifikasi = $src["guru_sertifikasi"];
        $des->jenjang_id = $this->getAndRegisterJenjangId($src["bentuk_pendidikan"]);
        $des->jml_lab = $src["lab_bahasa"] + $src['lab_ipa'] + $src['lab_ips'];
        $des->jml_perpus = $src["perpus"];
        $des->jml_rk = $src["ruang_kelas"];
        $des->kecamatan = $src["kecamatan"];
        $des->kepsek = $src["kepala_sekolah"];
        $des->kota_kab = $src["kabupaten_kota"];
        $des->kode_provinsi_dagri = trim($src["kode_provinsi_dagri"]);
        $des->kode_kabupaten_dagri = trim($src["kode_kabupaten_dagri"]);
        $des->kurikulum = $src["kurikulum"];
        $des->lab_bahasa = $src["lab_bahasa"];
//        $des->lab_biologi = $src["lab_biologi"];
//        $des->lab_fisika = $src["lab_fisika"];
        $des->lab_ipa = $src["lab_ipa"];
        $des->lab_ips = $src["lab_ips"];
//        $des->lab_kimia = $src["lab_kimia"];
        $des->laboratorium = $src["lab_bahasa"] + $src['lab_ipa'] + $src['lab_ips'];
        $des->latitude = $src["koordinat_lintang"];
        $des->longitude = $src["koordinat_bujur"];
        $des->luas_tanah_milik = $src["luas_tanah"];
        $des->nama = $src["sekolah"];
        $des->no_telp = $src["telp_sekolah"];
        $des->npsn = $src["npsn"];
        $des->pd_laki = $src["pd_l"];
        $des->pd_perempuan = $src["pd_p"];
        $des->periode_aktif = $src["periode_aktif"];
        $des->perpus_baik = $src["ruang_perpus_baik"];
        $des->perpus_rusak_berat = $src["ruang_perpus_rsk_berat"];
        $des->perpus_rusak_ringan = $src["ruang_perpus_rsk_ringan"];
        $des->perpus_rusak_sedang = $src["ruang_perpus_rsk_sedang"];
        $des->produk_id = "0fd356ad-5b4e-4f77-b7b4-f964be3731a3";
        $des->provinsi = $src["propinsi"];
        $des->rk_baik = $src["ruang_kelas_baik"];
        $des->rk_rusak_berat = $src["ruang_kelas_rsk_berat"];
        $des->rk_rusak_ringan = $src["ruang_kelas_rsk_berat"];
        $des->rk_rusak_sedang = $src["ruang_kelas_rsk_sedang"];
        $des->rombel = $src["rombel"];
//        $des->sanitasi_guru_baik = $src["sanitasi_guru_baik"];
//        $des->sanitasi_guru_rusak_berat = $src["sanitasi_guru_rusak_berat"];
//        $des->sanitasi_guru_rusak_ringan = $src["sanitasi_guru_rusak_ringan"];
        $des->sanitasi_siswa = $src["sanitasi_siswa"];
//        $des->sanitasi_siswa_baik = $src["sanitasi_siswa_baik"];
//        $des->sanitasi_siswa_rusak_berat = $src["sanitasi_siswa_rusak_berat"];
//        $des->sanitasi_siswa_rusak_sedang = $src["sanitasi_siswa_rusak_sedang"];
        $des->sekolah_id = $src["sekolah_id"];
        $des->tanggal_update_sekolah = $src["tanggal_update_sekolah"];
        $des->waktu_penyelenggaraan = $src["waktu_penyelenggaraan"];
        $des->status_sekolah = $src["status_sekolah"];
        $des->deleted_at = null;

        if (empty($des->kecamatan_kode)) {
            $kecamatanKodeRes = Sekolah::find(
                [
                    "columns" => "kecamatan_code",
                    "provinsi = :provinsi: and kota_kab = :kota_kab: and kecamatan = :kecamatan:",
                    "bind" => [
                        "provinsi" => $src["propinsi"],
                        "kota_kab" => $src["kabupaten_kota"],
                        "kecamatan" => $src["kecamatan"]
                    ],
                    "limit" => 1
                ]
            )
                ->toArray();
            if (count($kecamatanKodeRes) > 0) {
                $des->kecamatan_code = $kecamatanKodeRes[0]["kecamatan_code"];
            }
        }
        $res = $des->save();
        if (!$res) {
            if ($des->getMessages()[0]->getField() == "email") {
                $des->email = '';
                $res = $des->save();
            }
            print_r($des->getMessages());
        }
    }
}
