<?php
class DesaClient extends BackgroundBaseClient
{
    private $key;
    private $obj;
    private $type;

    private $tokenKey;

    public function key(string $key): void
    {
        $this->key = $key;
    }

    public function value($value): void
    {
        $this->obj[$this->key] = $value;
    }

    public function startObject(): void
    {
        $this->key = null;
        $this->obj = [];
    }

    public function endObject(): void
    {
        $this->objectsProcessed++;
        if ($this->type == 0) {
            $this->processDataDanaPaguDesa();
        } elseif ($this->type == 1) {
            $this->processDataPenyaluranDanaDesa();
        } elseif ($this->type == 2) {
            $this->processDataSp2dDanaDesa();
        }
    }

    public function filterResponse($body, $result)
    {
        parent::filterResponse($body, $result);
        if($this->logger != null) {
            if (count($result) == 1 && count($result[0]) == 1 && $result[0][0]['value'] == 'Tidak Ada Data') {
                $this->logger->addItem("api_result_code", -1);
                $this->logger->addItem("api_result_message", $result[0][0]['value']);
            }
        }
    }

    private function setTokenKey($tahun) {
        $tokenKey = "auth_token";
        if ($tahun > 2018) {
            $tokenKey .= "_" . $tahun;
        }
        $this->tokenKey = $tokenKey;
    }

    public function danaPaguDesa($tahun)
    {
        $this->setTokenKey($tahun);
        $this->objectsProcessed = 0;
        $this->type = 0;
        $method = "GET";
        $path = "/spanint/data/DataWebService/DataPaguDanaDesa";
        $params = [
            "headers" => [
                "Authorization" => $this->prop[$this->tokenKey]
            ],
            "verify" => false
        ];

        //region LOG Definition
        $this->setApiName("desa-dana_pagu");
        $this->setLogParams([
            'path' => $path
        ]);
        //endregion

        $this->jsonStream($method, $path, $params, $this);
    }

    public function penyaluranDanaDesa($tahun, $awalPeriode, $akhirPeriode, $kodeProvinsi, $kodePemda)
    {
        $this->setTokenKey($tahun);
        $this->objectsProcessed = 0;
        $this->type = 1;
        $method = "GET";
        $path = "/spanint/data/DataWebService/DataPenyaluranDanaDesa/$awalPeriode/$akhirPeriode/$kodeProvinsi/$kodePemda";
        $params = [
            "headers" => [
                "Authorization" => $this->prop[$this->tokenKey]
            ],
            "verify" => false
        ];

        //region LOG Definition
        $this->setApiName("desa-penyaluran_dana_desa");
        $this->setLogParams([
            'path' => $path
        ]);
        //endregion

        $this->jsonStream($method, $path, $params, $this);
    }

    public function sp2dDanaDesa($tahun)
    {
        $this->setTokenKey($tahun);
        $this->objectsProcessed = 0;
        $this->type = 2;
        $method = "GET";
        $path = "/spanint/data/DataWebService/DataSp2dDanaDesa";
        $params = [
            "headers" => [
                "Authorization" => $this->prop[$this->tokenKey]
            ],
            "verify" => false
        ];

        //region LOG Definition
        $this->setApiName("desa-sp2_dana_desa");
        //endregion

        $this->jsonStream($method, $path, $params, $this);
    }

    public function penyerapanDanaDesa($tahun, $kodeProv, $kodeKab)
    {
        try {
            $this->setTokenKey($tahun);
            $this->objectsProcessed = 0;
            $this->startTime = microtime(true);
            $this->type = 3;
            $method = "GET";
            $path = "/spanint/data/DataWebService/DataPenyerapanDanaDesa/$kodeProv/$kodeKab";
            $params = [
                "headers" => [
                    "Authorization" => $this->prop[$this->tokenKey]
                ],
                "verify" => false
            ];

            //region LOG Definition
            $this->setApiName("desa-penyerapan_dana_desa");
            $this->setLogParams([
                'path' => $path
            ]);
            //endregion

            $result = $this->execute($method, $path, $params);

            if (is_countable($result)) {
                if (count($result) == 1 && count($result[0]) == 1 && $result[0][0]['value'] == 'Tidak Ada Data') {
                    // Do Nothing
                } else {
                    // todo pertimbangkan untuk menghapus field id/serial dari table omspan_penyerapan_dana_desa
                    $existing = OmspanPenyerapanDanaDesa::find([
                        'conditions' => 'kode_lokasi = :kode_lokasi: and tahun = :tahun:',
                        'bind' => [
                            'kode_lokasi' => $kodeKab,
                            'tahun' => $tahun
                        ]
                    ]);
                    foreach ($existing as $exist) {
                        $exist->delete();
                    }
                    foreach ($result as $index => $entry) {
                        $this->processDataPenyerapanDanaDesa($entry);
                    }
                }
            }

            $this->endTime = microtime(true);
        } catch (\Exception $e) {
            // skip
            $this->endTime = microtime(true);
        }
    }

    private function processDataDanaPaguDesa()
    {

        if (
            !array_key_exists('KODE_LOKASI', $this->obj)
            || !array_key_exists('NM_KABKOTA', $this->obj)
            || !array_key_exists('KODE_DESA', $this->obj)
            || !array_key_exists('NM_DESA', $this->obj)
            || !array_key_exists('TAHUN', $this->obj)
            || !array_key_exists('PAGU', $this->obj)
            || !array_key_exists('STATUS_DESA', $this->obj)
            || !array_key_exists('PAGU_TAMBAHAN', $this->obj)
            || !array_key_exists('NM_KEC', $this->obj)
        ) {
            print_r("SOME DATA PAGU DESA CANNOT BE SAVED, here is the data: \n");
            print_r($this->obj);
        } else {
            $data = OmspanDanaDesaPagu::findFirst(
                [
                    "kode_desa = :kode_desa: and tahun = :tahun:",
                    "bind" => [
                        "kode_desa" => $this->obj["KODE_DESA"],
                        "tahun" => $this->obj["TAHUN"]
                    ]
                ]
            );
            $now = date('Y-m-d H:i:s');
            if (!$data) {
                $data = new OmspanDanaDesaPagu();
                $data->created_at = $now;
            }
            $data->kode_lokasi = $this->obj["KODE_LOKASI"];
            $data->kabupaten_kota = $this->obj["NM_KABKOTA"];
            $data->kode_desa = $this->obj["KODE_DESA"];
            $data->nama_desa = $this->obj["NM_DESA"];
            $data->tahun = $this->obj["TAHUN"];
            $data->pagu = $this->obj["PAGU"];
            $data->pagu_tambahan = $this->obj["PAGU_TAMBAHAN"];
            $data->status_desa = $this->obj["STATUS_DESA"];
            $data->kecamatan = $this->obj["NM_KEC"];
            $data->updated_at = $now;
            $res = $data->save();
            if (!$res) {
                print_r($data->getMessages());
                print_r($this->obj);
            }
        }

        $data = null;
    }

    private function processDataPenyaluranDanaDesa()
    {
        if(
            !array_key_exists('KODE_LOKASI', $this->obj)
            || !array_key_exists('NM_KABKOTA', $this->obj)
            || !array_key_exists('KODE_DESA', $this->obj)
            || !array_key_exists('NM_DESA', $this->obj)
            || !array_key_exists('TAHUN', $this->obj)
            || !array_key_exists('TAHAP', $this->obj)
            || !array_key_exists('NO_SP2D', $this->obj)
            || !array_key_exists('TGL_SP2D', $this->obj)
            || !array_key_exists('REALISASI', $this->obj)
        ) {
            print_r("SOME DATA PENYALURAN DANA DESA CANNOT BE SAVED, here is the data: \n");
            print_r($this->obj);
        }
        else {
            $data = OmspanDanaDesaPenyaluran::findFirst(
                [
                    "kode_desa = :kode_desa: and tahun = :tahun: and tahap = :tahap: and no_sp2d = :no_sp2d:",
                    "bind" => [
                        "kode_desa" => $this->obj["KODE_DESA"],
                        "tahun" => $this->obj["TAHUN"],
                        "tahap" => $this->obj["TAHAP"],
                        "no_sp2d" => $this->obj["NO_SP2D"],
                    ]
                ]
            );

            $now = date('Y-m-d H:i:s');
            if (!$data) {
                $data = new OmspanDanaDesaPenyaluran();
                $data->created_at = $now;
            }

            $data->kode_lokasi = $this->obj["KODE_LOKASI"];
            $data->kabupaten_kota = $this->obj["NM_KABKOTA"];
            $data->kode_desa = $this->obj["KODE_DESA"];
            $data->nama_desa = $this->obj["NM_DESA"];
            $data->tahun = $this->obj["TAHUN"];
            $data->tahap = $this->obj["TAHAP"];
            $data->no_sp2d = $this->obj["NO_SP2D"];
            $data->tanggal_sp2d = $this->obj["TGL_SP2D"];
            $data->realisasi = $this->obj["REALISASI"];
            $data->updated_at = $now;
            $res = $data->save();
            if (!$res) {
                print_r($data->getMessages());
                print_r($this->obj);
            }
        }

        $data = null;
    }

    private function processDataSp2dDanaDesa()
    {
        if(
            !array_key_exists('KODE_LOKASI', $this->obj)
            || !array_key_exists('NM_LOKASI', $this->obj)
            || !array_key_exists('TRIWULAN', $this->obj)
            || !array_key_exists('NO_SP2D', $this->obj)
            || !array_key_exists('TGL_SP2D', $this->obj)
            || !array_key_exists('NILAI', $this->obj)
        ) {
            print_r("SOME DATA SP2D DANA DESA CANNOT BE SAVED, here is the data: \n");
            print_r($this->obj);
        }
        else {
            $data = OmspanDanaDesaRkunRkud::findFirst(
                [
                    "triwulan = :triwulan: and no_sp2d = :no_sp2d:",
                    "bind" => [
                        "triwulan" => $this->obj["TRIWULAN"],
                        "no_sp2d" => $this->obj["NO_SP2D"]
                    ]
                ]
            );
            if (!$data) {
                $data = new OmspanDanaDesaPenyaluran();
            }

            $data->kode_lokasi = $this->obj["KODE_LOKASI"];
            $data->kabupaten_kota = $this->obj["NM_LOKASI"];
            $data->tahun = date("Y");
            $data->triwulan = $this->obj["TRIWULAN"];
            $data->no_sp2d = $this->obj["NO_SP2D"];
            $data->tanggal_sp2d = $this->obj["TGL_SP2D"];
            $data->nilai = $this->obj["NILAI"];
            $res = $data->save();
            if (!$res) {
                print_r($data->getMessages());
                print_r($this->obj);
            }
        }

        $data = null;
    }

    private function processDataPenyerapanDanaDesa($entry)
    {
        try {
            $this->objectsProcessed++;

            $uraianOutput = DesaUraianOutputPenyerapan::findFirst(
                [
                    "kode = :kode:",
                    "bind" => [
                        "kode" => $entry["KD_URAIAN_OUTPUT"]
                    ]
                ]
            );

            if (!$uraianOutput) {
                // uraian output not found
                // we need to register new uraian output
                // first check if kegiatan already exist
                $kegiatan = DesaKegiatanPenyerapan::findFirst(
                    [
                        "kode = :kode:",
                        "bind" => [
                            "kode" => $entry["KODE_KEGIATAN"]
                        ]
                    ]
                );

                if (!$kegiatan) {
                    // kegiatan not found
                    // we need to register new kegiatan
                    // first check if bidang already exists
                    $bidang = DesaBidangPenyerapan::findFirst(
                        [
                            "kode = :kode:",
                            "bind" => [
                                "kode" => $entry["KODE_BIDANG"]
                            ]
                        ]
                    );

                    if (!$bidang) {
                        // bidang not found
                        // we need to register new bidang
                        $bidang = new DesaBidangPenyerapan();
                        $bidang->kode = $entry["KODE_BIDANG"];
                        $bidang->nama = $entry["NM_BIDANG"];
                        if (!$bidang->create()) {
                            print_r($bidang->getMessages());
                            return;
                        }
                    }

                    // at this point bidang already registered
                    // so it's safe to save kegiatan
                    $kegiatan = new DesaKegiatanPenyerapan();
                    $kegiatan->kode = $entry["KODE_KEGIATAN"];
                    $kegiatan->nama = $entry["NM_KEGIATAN"];
                    $kegiatan->kode_bidang = $entry["KODE_BIDANG"];
                    if (!$kegiatan->create()) {
                        print_r($kegiatan->getMessages());
                        return;
                    }
                }

                // at this point kegiatan already registered
                // so it's safe to save uraian output
                $uraianOutput = new DesaUraianOutputPenyerapan();
                $uraianOutput->kode = $entry["KD_URAIAN_OUTPUT"];
                $uraianOutput->uraian = $entry["URAIAN_OUTPUT"];
                $uraianOutput->kode_kegiatan = $entry["KODE_KEGIATAN"];
                if (!$uraianOutput->create()) {
                    print_r($uraianOutput->getMessages());
                    return;
                }
            }

            // check if desa exists in desa_master_desa
//        $desa = OmspanMasterDesa::findFirst(
//            [
//                "kode_desa = :kode:",
//                "bind" => [
//                    "kode" => $entry["KODE_DESA"]
//                ]
//            ]
//        );

            // if (!$desa) {
            // desa not found
            // unfortunately if desa is not found then we need to finish the process, at least for now
            // we cannot register desa either because of insufficient data
            // return;
            // }

            // all referenced data are set
            // process penyerapan data
            // update 19072022, untuk kode uraian output yang sama, bisa lebih dari 1 row,
            // sehingga tidak ada key pasti untuk memetakan data penyerapan yang telah ada sebelumnya
            // karena hal tsb, semua data pada kabupaten telah dihapus terlebih dahulu

//        $conditions = "kode_desa = :kode_desa: and tahun = :tahun: and kode_uraian_output = :kode_uraian_output:";
//        $bind = [
//            "kode_desa" => $entry["KODE_DESA"],
//            "tahun" => $entry["TAHUN"],
//            "kode_uraian_output" => $entry["KD_URAIAN_OUTPUT"]
//        ];
//        if (is_null($entry["KETERANGAN"])) {
//            $conditions .= " and keterangan IS NULL";
//        } else {
//            $conditions .= " and keterangan = :keterangan:";
//            $bind['keterangan'] = $entry["KETERANGAN"];
//        }
//        $data = OmspanPenyerapanDanaDesa::findFirst(
//            [
//                "conditions" => $conditions,
//                "bind" => $bind
//            ]
//        );
//        if (!$data) {
//            $data = new OmspanPenyerapanDanaDesa();
//            $data->kode_desa = $entry["KODE_DESA"];
//            $data->tahun = $entry["TAHUN"];
//            $data->kode_uraian_output = $entry["KD_URAIAN_OUTPUT"];
//            $data->keterangan = $entry["KETERANGAN"];
//        }

            $now = date('Y-m-d H:i:s');
            $data = new OmspanPenyerapanDanaDesa();
            $data->kode_desa = $entry["KODE_DESA"];
            $data->tahun = $entry["TAHUN"];
            $data->kode_uraian_output = $entry["KD_URAIAN_OUTPUT"];
            $data->keterangan = $entry["KETERANGAN"];

            $data->kode_lokasi = $entry["KODE_LOKASI"];
            $data->volume = $entry["VOLUME"];
            $data->satuan_output = $entry["SATUAN_OUTPUT"];
            $data->cara_pengadaan = $entry["CARA_PENGADAAN"];

            $data->created_at = $now;
            $data->updated_at = $now;

            if ($entry["REALISASI"] != null) {
                $data->realisasi_tahap_1 = $entry["REALISASI"];
            }
            if ($entry["REALISASI2"] != null) {
                $data->realisasi_tahap_2 = $entry["REALISASI2"];
            }
            if ($entry["REALISASI3"] != null) {
                $data->realisasi_tahap_3 = $entry["REALISASI3"];
            }

            if ($entry["PERSENTASE"] != null) {
                $data->persentase_realisasi_tahap_1 = $entry["PERSENTASE"];
            }
            if ($entry["PERSENTASE2"] != null) {
                $data->persentase_realisasi_tahap_2 = $entry["PERSENTASE2"];
            }
            if ($entry["PERSENTASE3"] != null) {
                $data->persentase_realisasi_tahap_3 = $entry["PERSENTASE3"];
            }

            if (!$data->save()) {
                print_r($data->getMessages());
            }
        } catch (\Exception $e) {
            // skip
        }
    }
}
