<?php

class BosController extends BaseController
{
    public function list_provinsi()
    {
        $validatedRequest = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']]
            ]
        );

        $class = 'SekolahDanaBos' . $validatedRequest['tahun'];
        if (class_exists($class)) {
            $result = array_map(
                function ($v) {
                    return $v['prov'];
                },
                $class::find(
                    array(
                        'columns' => 'prov',
                        'group' => 'prov'
                    )
                )
                    ->toArray()
            );
        } else {
            $result = [];
        }


        $totalResult = count($result);
        return new PaginatedResponse($result, $totalResult, $totalResult, 0);
    }

    public function list_kota_kabupaten()
    {
        $validatedRequest = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'provinsi' => ['validators' => ['required']]
            ]
        );

        $class = 'SekolahDanaBos' . $validatedRequest['tahun'];
        if (class_exists($class)) {
            $result = array_map(
                function ($v) {
                    return $v['kab'];
                },
                $class::find(
                    array(
                        'columns' => 'kab',
                        'prov = :prov:',
                        'group' => 'kab',
                        'bind' => array(
                            'prov' => $validatedRequest['provinsi']
                        )
                    )
                )
                    ->toArray()
            );
        } else {
            $result = [];
        }

        $totalResult = count($result);
        return new PaginatedResponse($result, $totalResult, $totalResult, 0);
    }

    public function list_kecamatan()
    {
        $validatedRequest = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'kota_kabupaten' => ['validators' => ['required']]
            ]
        );

        $class = 'SekolahDanaBos' . $validatedRequest['tahun'];
        if (class_exists($class)) {
            $result = array_map(
                function ($v) {
                    return $v['kec'];
                },
                $class::find(
                    array(
                        'columns' => 'kec',
                        'kab = :kab:',
                        'group' => 'kec',
                        'bind' => array(
                            'kab' => $validatedRequest['kota_kabupaten']
                        )
                    )
                )
                    ->toArray()
            );
        } else {
            $result = [];
        }

        $totalResult = count($result);
        return new PaginatedResponse($result, $totalResult, $totalResult, 0);
    }

    public function summary_kecamatan()
    {
        $validatedRequest = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'kecamatan' => ['validators' => ['required']]
            ]
        );

        $class = 'SekolahDanaBos' . $validatedRequest['tahun'];
        if (class_exists($class)) {
            $result = $class::find(
                array(
                    'columns' => 'bentuk, count(DISTINCT(npsn)) as total_sekolah',
                    'kec = :kec:',
                    'group' => 'bentuk',
                    'bind' => array(
                        'kec' => $validatedRequest['kecamatan']
                    )
                )
            )
                ->toArray();
        } else {
            $result = [];
        }

        $totalResult = count($result);
        return new PaginatedResponse($result, $totalResult, $totalResult, 0);
    }

    public function list_sekolah()
    {
        $params = $this->request->get();

        $params['limit'] = $this->getDefaultLimit($params);
        $params['offset'] = array_key_exists('offset', $params) ? $params['offset'] : 0;
        $params['keyword'] = array_key_exists('keyword', $params) ? $params['keyword'] : '';
        $params['jenjang'] = array_key_exists('jenjang', $params) ? $params['jenjang'] : 'true';

        $validatedRequest = $this->validate(
            $params,
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'kecamatan' => ['validators' => ['required']],
                'limit' => ['validators' => ['digit']],
                'offset' => ['validators' => ['digit']]
            ]
        );

        if ($params['jenjang'] != 'true') {
            $params['jenjang'] = 'bentuk = ' . $params['jenjang'];
        }

        $arrParams = array(
            'columns' => 'count(1) as jumlah',
            'kec = :kec: and lower(nama_sekolah) like :nama_sekolah: and :jenjang:',
            'bind' => array(
                'kec' => $params['kecamatan'],
                'nama_sekolah' => '%' . strtolower($params['keyword']) . '%',
                'jenjang' => $params['jenjang']
            )
        );

        $class = 'SekolahDanaBos' . $validatedRequest['tahun'];
        if (class_exists($class)) {
            $result = $class::find(
                $arrParams
            )
                ->toArray();
            $totalResult = (int)$result[0]['jumlah'];

            $arrParams['columns'] = 'npsn, nama_sekolah, bentuk';
            $arrParams['limit'] = $params['limit'];
            $arrParams['offset'] = $params['offset'];

            $result = $class::find(
                $arrParams
            )
                ->toArray();
        } else {
            $result = [];
            $totalResult = 0;
        }

        return new PaginatedResponse($result, $totalResult, $params['limit'], $params['offset']);
    }

    // komponen bos 2020 - sekarang
    private $namaKomponenBos2020 = [
        '1' => 'penerimaan Peserta Didik baru',
        '2' => 'pengembangan perpustakaan',
        '3' => 'kegiatan pembelajaran dan ekstrakurikuler',
        '4' => 'kegiatan asesmen/evaluasi pembelajaran',
        '5' => 'administrasi kegiatan sekolah',
        '6' => 'pengembangan profesi guru dan tenaga kependidikan',
        '7' => 'langganan daya dan jasa',
        '8' => 'pemeliharaan sarana dan prasarana Sekolah',
        '9' => 'penyediaan alat multi media pembelajaran',
        '10' => 'penyelenggaraan bursa kerja khusus, praktik kerja industri atau praktik kerja lapangan di dalam negeri, pemantauan kebekerjaan, pemagangan guru, dan lembaga sertifikasi profesi pihak pertama',
        '11' => 'penyelenggaraan kegiatan uji kompetensi keahlian, sertifikasi kompetensi keahlian dan uji kompetensi kemampuan bahasa Inggris berstandar internasional dan bahasa asing lainnya bagi kelas akhir SMK atau SMALB',
        '12' => 'pembayaran honor',
    ];

    // komponen bos 2018
    private $namaKomponenBosSma = [
        '1' => 'Pengembangan Perpustakaan',
        '2' => 'Langganan Daya dan Jasa',
        '3' => 'Kegiatan Pembelajaran & Ekstrakurikuler',
        '4' => 'Kegiatan Evaluasi Pembelajaran',
        '5' => 'Pengelolaan Sekolah',
        '6' => 'Pengembangan Profesi Guru dan Tenaga Kependidikan, serta Pengembangan Manajemen Sekolah',
        '7' => 'Penerimaan Siswa Baru',
        '8' => 'Pemeliharaan dan Perawatan Sarana dan Prasarana Sekolah',
        '9' => 'Pembayaran Honor',
        '10' => 'Pembelian Alat Multi Media Pembelajaran',
        '11' => 'Lainnya (Komponen 11)',
        '12' => 'Lainnya (Komponen 12)',
        '1a' => 'Buku Teks K-13 Untuk Siswa',
        '1b' => 'Buku Teks K-13 Untuk Guru',
        '1c' => 'Buku Teks Kurikulum 2006 (KTSP) Untuk Siswa',
        '1d' => 'Buku Teks Kurikulum 2006 (KTSP) Untuk Guru',
        '1e' => 'Pengembangan Perpustakaan Lainnya - Pengembangan Non Buku Text',
    ];

    private $namaKomponenBosMadrasah = [
        '1' => 'Untuk penerimaan peserta didik baru',
        '2' => 'Untuk pengebangan perpustakaan',
        '3' => 'Untuk kegiatan pembelajaran dan ekstrakurikuler',
        '4' => 'Untuk biaya asesmen atau evaluasi pembelajaran',
        '5' => 'Untuk administrasi kegiatan sekolah',
        '6' => 'Untuk pengembangan kegiatan profesi guru dan tenaga kependidikan',
        '7' => 'Untuk biaya langganan daya dan jasa',
        '8' => 'Untuk pemeliharaan sarana dan prasarana sekolah',
        '9' => 'Untuk penyediaan alat multimedia pembelajaran',
        '10' => 'Untuk penyelenggaraan bursa kerja khusus, praktek kerja industri atau praktek kerja lapangan di dalam negeri, pemantauan kebekerjaan, pemagangan guru, dan lembaga sertifikasi profesi pihak pertama',
        '11' => 'Untuk penyelenggaraan uji kompetensi keahlian, sertifikasi kompetensi keahlian dan uji kompetensi kemampuan bahasa inggris berstandar internasional dan bahasa asing lainnya bagi kelas akhir SMK atau SMALB',
        '11a' => 'Biaya Komponen 11',
        '12' => 'Untuk pembayaran honor',
        '13' => 'Komponen lainnya',
    ];

    public function detail()
    {
        $validatedRequest = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'npsn' => ['validators' => ['required']]
            ]
        );
        $result = [];
        $sekolah = Sekolah::findFirstByNpsn($validatedRequest["npsn"]);

        if (empty($sekolah)) {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, 'Not Found');
        }

        if (
            $sekolah->jenjang->nama_jenjang == Sekolah::MADRASAH_JENJANG_MAS
            || $sekolah->jenjang->nama_jenjang == Sekolah::MADRASAH_JENJANG_MAN
        ) {
            $data = array();
            $data['source'] = "KEMENAG";
            $data['npsn'] = $validatedRequest["npsn"];
            $data['perencanaan_bos'] = null;
            $data['realisasi_bos'] = null;
            $bosClient = new MadrasahClient($this->config["madrasah_prop"]);
            $bosClient->setLogger($this->logger);
            $api_params = http_build_query($validatedRequest);
            try {
                $res = $bosClient->get_data($validatedRequest['npsn'], Sekolah::MADRASAH_JENISDATA_BOS);
                if (!empty($res) && count($res) >= 2) {
                    $data['perencanaan_bos'] = $res[0];
                    $data['realisasi_bos'] = $this->generateBosMadrasahDynamyc($res[1]);
                    $result[0] = $data;
                }
            } catch (\Exception $ex) {
                $this->apiLog->log_error("Madrasah-BOS", $api_params, $ex->getMessage());
                throw $ex;
            }
        } else {
            $api_params = http_build_query($validatedRequest);
            $tahun = $validatedRequest['tahun'];
            $class = 'SekolahDanaBos' . $tahun;
            if (class_exists($class)) {
                $bosClient = new NeoBosClient($this->config["neo_bos_prop"]);
                $bosClient->setLogger($this->logger);
                /**
                 * tahun < 2022 ada 4 triwulan
                 * tahun 2022 ada 3 tahap
                 * tahun > 2022 ada 2 tahap, tahap 2 mulai berlaku setelah 31 Januari [tahun berjalan + 1]
                 */
                $upper = 4;
                if ($tahun == 2022) $upper = 3;
                elseif ($tahun == 2023) $upper = 2;
                elseif ($tahun == (date('Y') - 1) && date('n') > 1) $upper = 2;
                elseif ($tahun == date('Y')) $upper = 1;
                for ($i = 1; $i <= $upper; $i++) {
                    try {
                        $res = $bosClient->getLaporanByNpsn($validatedRequest['npsn'], $validatedRequest['tahun'], $i);
                    } catch (\Exception $e) {
                        $res = [];
                    }
                    if (array_key_exists("success", $res) && $res["success"] == 1) {
                        if (
                            (array_key_exists('return', $res) && array_key_exists('penggunaan', $res['return']) && count($res["return"]["penggunaan"]) > 0)
                            ||
                            (array_key_exists('return', $res) && array_key_exists('pencairan', $res['return']) && count($res["return"]["pencairan"]) > 0)
                        ) {
                            $realisasiTersedia = 0;
                            $result[$i - 1]["total_dana_tahap_ini"] = 0;
                            $bos = null;
                            if ((array_key_exists('penggunaan', $res['return']) && count($res["return"]["penggunaan"]) > 0)) {
                                $bos = $this->generateBosFromResultPenggunaan($class, $res["return"]["penggunaan"]);
                                $realisasiTersedia = 1;
                                $result[$i - 1] = $this->generateBosSekolahDynamic($res["return"]["penggunaan"]);
                            }

                            $result[$i - 1]["data_realisasi_tersedia"] = $realisasiTersedia;
                            if (array_key_exists('pencairan', $res['return']) && count($res["return"]["pencairan"]) > 0) {
                                $bos = $this->generateBosFromResultPencairan($class, $res["return"]["pencairan"], $bos);
                                $result[$i - 1] = $this->prosesPencairan($result[$i - 1], $res["return"]["pencairan"]);
                                if ($realisasiTersedia == 0) {
                                    $result[$i - 1] = $this->addSekolahInfo($result[$i - 1], $res["return"]["pencairan"]);
                                }
                            }
                            if ($bos) $bos->save();
                        } else {
                            $result[$i - 1] = [];
                            $result[$i - 1]["total_dana_tahap_ini"] = 0;
                        }
                    } else {
                        $bos = $class::findFirst([
                            'conditions' => 'npsn = :npsn: AND triwulan = :triwulan:',
                            'bind' => [
                                'npsn' => $validatedRequest['npsn'],
                                'triwulan' => $i
                            ]
                        ]);

                        if ($bos) {
                            $res = $bos->toArray();
                            $result[$i - 1]["total_dana_tahap_ini"] = 0;
                            $result[$i - 1]["data_realisasi_tersedia"] = 1;
                            $result[$i - 1] = $this->generateBosSekolahDynamic($res);
                            $result[$i - 1] = $this->prosesPencairan($result[$i - 1], $res);
                        }
                    }
                }
            } else {
                $this->apiLog->log_error("BOS-getLaporanByNpsn", $api_params, "Class $class tidak ditemukan");
            }
        }

        $totalResult = count($result);
        if ($totalResult == 0) {
            $isBosFound = PenerimaBos::isFoundByNpsnTahun($validatedRequest['npsn'], $validatedRequest['tahun']);
            if (!$isBosFound) {
                $message = 'tidak menerima Dana BOS';
            } else {
                $message = 'belum tersedia di Kementerian Pendidikan dan Kebudayaan';
            }

            return new SimpleResponse(['message' => $message]);
        } else {
            return new PaginatedResponse($result, $totalResult, $totalResult, 0);
        }
    }

    public function summaryNasionalPerJenjang()
    {
        $params = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']],
            ]
        );

        $bosClient = new NeoBosClient($this->config["neo_bos_prop"]);
        $bosClient->setLogger($this->logger);

        $result = $bosClient->getSummaryNasionalPerJenjang($params['tahun']);

        if ($result['success'] == 1) {
            return new CollectionPaginatedResponse($result['return']);
        } else {
            $api_params = http_build_query($params);
            $errorMessage = is_array($result) && array_key_exists('error', $result) ? $result['error'] : $bosClient->getErrorBody();

            $this->apiLog->log_error("BOS-summaryNasionalPerJenjang", $api_params, $errorMessage);

            //throw new CustomErrorException(BaseResponse::GUZZLE_ERROR, 'API BOS Error: ' .  $errorMessage);
            throw new CustomErrorException(BaseResponse::GUZZLE_ERROR, 'Gagal menghubungi server BOS KemenDikBud');
        }
    }

    public function summaryNasionalPerKomponen()
    {
        $params = $this->validate($this->request->get(), [
            'tahun' => ['validators' => ['required', 'digit']],
        ]);

        $result = BosRekapitulasiNasionalKomponen::find([
            'conditions' => 'tahun = :tahun:',
            'bind' => [
                'tahun' => $params['tahun']
            ]
        ]);

        return new CollectionPaginatedResponse($result);
    }

    /**
     * API ini menggantikan summaryNasionalPerKomponen
     * @return SimpleResponse
     * @throws CustomErrorException
     * @throws ValidationException
     */
    public function laporanKomponenNasional()
    {
        $params = $this->validate(
            $this->request->get(),
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'jenis_bos' => ['validators' => [
                    'required',
                    [
                        'name' => 'inclusion_in',
                        'params' => NeoBosClient::JENIS_BOS
                    ]
                ]],
            ]
        );

        $bosClient = new NeoBosClient($this->config["neo_bos_prop"]);
        $bosClient->setLogger($this->logger);

        $result = $bosClient->getLaporanKomponenNasional($params['tahun'], $params['jenis_bos']);

        if (array_key_exists('data', $result) && is_array($result['data'])) {
            return new SimpleResponse($result['data']);
        } else {
            $api_params = http_build_query($params);
            $errorMessage = is_array($result) && array_key_exists('error', $result) ? $result['error'] : $bosClient->getErrorBody();
            $bosClient->apiLog->log_error("BOS", $api_params, $errorMessage);
            throw new CustomErrorException(BaseResponse::GUZZLE_ERROR, 'Gagal menghubungi server BOS KemenDikBud');
        }
    }

    public function jenisBos()
    {
        return new SimpleResponse(NeoBosClient::JENIS_BOS);
    }

    private function generateBosFromResultPenggunaan($class, $penggunaan)
    {
        $bos = $class::findFirst([
            'conditions' => 'sekolah_id = :sekolah_id: AND npsn = :npsn: AND triwulan = :triwulan:',
            'bind' => [
                'sekolah_id' => $this->getValue($penggunaan, "sekolah_id"),
                'npsn' => $this->getValue($penggunaan, "npsn"),
                'triwulan' => $this->getValue($penggunaan, "triwulan")
            ]
        ]);
        if (!$bos) {
            $bos = new $class();
        }
        $bos->sekolah_id = $penggunaan["sekolah_id"];
        $bos->nama_sekolah = $penggunaan["nama_sekolah"];
        if ($penggunaan["status_sekolah"] == "N") {
            $bos->status = "negeri";
        } else {
            $bos->status = $penggunaan["status_sekolah"];
        }
        $bos->npsn = $this->getValue($penggunaan, "npsn");
        $bos->bentuk = $this->getValue($penggunaan, "jenjang");
        $bos->triwulan = $this->getValue($penggunaan, "triwulan");
        $bos->komponen_1 = $this->getValue($penggunaan, "komponen_1");
        $bos->komponen_1_nama = $this->getValue($penggunaan, "komponen_1_nama");
        $bos->komponen_2 = $this->getValue($penggunaan, "komponen_2");
        $bos->komponen_2_nama = $this->getValue($penggunaan, "komponen_2_nama");
        $bos->komponen_3 = $this->getValue($penggunaan, "komponen_3");
        $bos->komponen_3_nama = $this->getValue($penggunaan, "komponen_3_nama");
        $bos->komponen_4 = $this->getValue($penggunaan, "komponen_4");
        $bos->komponen_4_nama = $this->getValue($penggunaan, "komponen_4_nama");
        $bos->komponen_5 = $this->getValue($penggunaan, "komponen_5");
        $bos->komponen_5_nama = $this->getValue($penggunaan, "komponen_5_nama");
        $bos->komponen_6 = $this->getValue($penggunaan, "komponen_6");
        $bos->komponen_6_nama = $this->getValue($penggunaan, "komponen_6_nama");
        $bos->komponen_7 = $this->getValue($penggunaan, "komponen_7");
        $bos->komponen_7_nama = $this->getValue($penggunaan, "komponen_7_nama");
        $bos->komponen_8 = $this->getValue($penggunaan, "komponen_8");
        $bos->komponen_8_nama = $this->getValue($penggunaan, "komponen_8_nama");
        $bos->komponen_9 = $this->getValue($penggunaan, "komponen_9");
        $bos->komponen_9_nama = $this->getValue($penggunaan, "komponen_9_nama");
        $bos->komponen_10 = $this->getValue($penggunaan, "komponen_10");
        $bos->komponen_10_nama = $this->getValue($penggunaan, "komponen_10_nama");
        $bos->komponen_11 = $this->getValue($penggunaan, "komponen_11");
        $bos->komponen_11_nama = $this->getValue($penggunaan, "komponen_11_nama");
        $bos->komponen_12 = $this->getValue($penggunaan, "komponen_12");
        $bos->komponen_12_nama = $this->getValue($penggunaan, "komponen_12_nama");
        $bos->komponen_1_a_1 = $this->getValue($penggunaan, "komponen_1_a_1");
        $bos->komponen_1_a_2 = $this->getValue($penggunaan, "komponen_1_a_2");
        $bos->komponen_1_b_1 = $this->getValue($penggunaan, "komponen_1_b_1");
        $bos->komponen_1_b_2 = $this->getValue($penggunaan, "komponen_1_b_2");
        $bos->komponen_1_c_1 = $this->getValue($penggunaan, "komponen_1_c_1");
        $bos->komponen_1_c_2 = $this->getValue($penggunaan, "komponen_1_c_2");
        $bos->komponen_1_d_1 = $this->getValue($penggunaan, "komponen_1_d_1");
        $bos->komponen_1_d_2 = $this->getValue($penggunaan, "komponen_1_d_2");
        $bos->komponen_1_e_1 = $this->getValue($penggunaan, "komponen_1_e_1");
        return $bos;
    }

    private function generateBosFromResultPencairan($class, $pencairan, $bosObject)
    {
        if (!$bosObject) {
            $bos = $class::findFirst([
                'conditions' => 'sekolah_id = :sekolah_id: AND npsn = :npsn: AND triwulan = :triwulan:',
                'bind' => [
                    'sekolah_id' => $this->getValue($pencairan, "sekolah_id"),
                    'npsn' => $this->getValue($pencairan, "npsn"),
                    'triwulan' => $this->getValue($pencairan, "triwulan")
                ]
            ]);
        } else {
            $bos = $bosObject;
        }
        if (!$bos) {
            $bos = new $class();
        }
        $bos->prov = $pencairan["provinsi"];
        $bos->kab = $pencairan["kabkota"];
        $bos->jumlah_dana = $this->getValue($pencairan, "jumlah_dana");
        $bos->jumlah_pengurang = $this->getValue($pencairan, "jumlah_pengurang");
        $bos->tanggal_sp2d = $this->getValue($pencairan, "tanggal_sp2d");
        $bos->tanggal_cut_off = $this->getValue($pencairan, "tanggal_cut_off");
        $bos->jumlah_siswa = $this->getValue($pencairan, "jumlah_siswa");
        $bos->status_salur = $this->getValue($pencairan, "status_salur");
        $bos->lapor_penggunaan = $this->getValue($pencairan, "lapor_penggunaan");
        $bos->lapor_penggunaan_nama = $this->getValue($pencairan, "lapor_penggunaan_nama");
        $bos->konfirmasi_sekolah = $this->getValue($pencairan, "konfirmasi_sekolah");
        $bos->konfirmasi_sekolah_nama = $this->getValue($pencairan, "konfirmasi_sekolah_nama");
        return $bos;
    }

    private function generateBosSekolahDynamic(array $dataBos) {
        $result = [];
        $result['sekolah_id'] = $dataBos["sekolah_id"];
        $result['nama_sekolah'] = $dataBos["nama_sekolah"];
        $result['npsn'] = $dataBos["npsn"] ?? null;
        $result['bentuk'] = $dataBos["bentuk"] ?? null;
        $result['triwulan'] = $dataBos["triwulan"] ?? null;
        $result['komponen_1'] = $this->getValue($dataBos, "komponen_1");
        $result['komponen_1_nama'] = $this->getValue($dataBos, "komponen_1_nama");
        $result['komponen_2'] = $this->getValue($dataBos, "komponen_2");
        $result['komponen_2_nama'] = $this->getValue($dataBos, "komponen_2_nama");
        $result['komponen_3'] = $this->getValue($dataBos, "komponen_3");
        $result['komponen_3_nama'] = $this->getValue($dataBos, "komponen_3_nama");
        $result['komponen_4'] = $this->getValue($dataBos, "komponen_4");
        $result['komponen_4_nama'] = $this->getValue($dataBos, "komponen_4_nama");
        $result['komponen_5'] = $this->getValue($dataBos, "komponen_5");
        $result['komponen_5_nama'] = $this->getValue($dataBos, "komponen_5_nama");
        $result['komponen_6'] = $this->getValue($dataBos, "komponen_6");
        $result['komponen_6_nama'] = $this->getValue($dataBos, "komponen_6_nama");
        $result['komponen_7'] = $this->getValue($dataBos, "komponen_7");
        $result['komponen_7_nama'] = $this->getValue($dataBos, "komponen_7_nama");
        $result['komponen_8'] = $this->getValue($dataBos, "komponen_8");
        $result['komponen_8_nama'] = $this->getValue($dataBos, "komponen_8_nama");
        $result['komponen_9'] = $this->getValue($dataBos, "komponen_9");
        $result['komponen_9_nama'] = $this->getValue($dataBos, "komponen_9_nama");
        $result['komponen_10'] = $this->getValue($dataBos, "komponen_10");
        $result['komponen_10_nama'] = $this->getValue($dataBos, "komponen_10_nama");
        $result['komponen_11'] = $this->getValue($dataBos, "komponen_11");
        $result['komponen_11_nama'] = $this->getValue($dataBos, "komponen_11_nama");
        $result['komponen_12'] = $this->getValue($dataBos, "komponen_12");
        $result['komponen_12_nama'] = $this->getValue($dataBos, "komponen_12_nama");
        $result['komponen_1_a_1'] = $this->getValue($dataBos, "komponen_1_a_1");
        $result['komponen_1_a_2'] = $this->getValue($dataBos, "komponen_1_a_2");
        $result['komponen_1_b_1'] = $this->getValue($dataBos, "komponen_1_b_1");
        $result['komponen_1_b_2'] = $this->getValue($dataBos, "komponen_1_b_2");
        $result['komponen_1_c_1'] = $this->getValue($dataBos, "komponen_1_c_1");
        $result['komponen_1_c_2'] = $this->getValue($dataBos, "komponen_1_c_2");
        $result['komponen_1_d_1'] = $this->getValue($dataBos, "komponen_1_d_1");
        $result['komponen_1_d_2'] = $this->getValue($dataBos, "komponen_1_d_2");
        $result['komponen_1_e_1'] = $this->getValue($dataBos, "komponen_1_e_1");
        $result['komponen_penggunaan'] = [];
        $result['total_penggunaan'] = 0;
        $counter = 1;
        $komponenExist = array_key_exists('komponen_' . $counter, $dataBos) && !is_null($dataBos['komponen_' . $counter]);

        while ($komponenExist) {
            $item = [];
            $item['dana'] = $dataBos['komponen_' . $counter];
            $result['total_penggunaan'] += (is_numeric($item['dana']) ? doubleval($item['dana']) : 0);
            $item['nama'] = $dataBos['komponen_' . $counter . "_nama"] ?? (array_key_exists($counter, $this->namaKomponenBos2020) ? $this->namaKomponenBos2020[$counter] : 'komponen_' . $counter);
            $childCharCounter = 'a';
            $childExist = (
                (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_1', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_1']))
                || (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_2', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_2']))
                || (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_1_nama', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_1_nama']))
                || (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_2_nama', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_2_nama']))
            );
            $childs = [];
            while ($childExist) {
                $childItem = [
                    'nama' => '',
                    'nama_unit' => '',
                    'nama_dana' => '',
                    'total_unit' => null,
                    'total_dana' => null
                ];
                $childItem['nama'] = $this->namaKomponenBos2020[$counter . $childCharCounter] ?? 'komponen_' . $counter . '_' . $childCharCounter;
                $childItem['nama_unit'] = $dataBos['komponen_' . $counter . '_' . $childCharCounter . '_1_nama' ] ?? "";
                $childItem['nama_dana'] = $dataBos['komponen_' . $counter . '_' . $childCharCounter . '_2_nama' ] ?? "";
                $childItem['total_unit'] = $dataBos['komponen_' . $counter . '_' . $childCharCounter . '_1' ] ?? 0;
                $childItem['total_dana'] = $dataBos['komponen_' . $counter . '_' . $childCharCounter . '_2' ] ?? 0;
                array_push($childs, $childItem);
                ++$childCharCounter;
                $childExist = (
                    (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_1', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_1']))
                    || (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_2', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_2']))
                    || (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_1_nama', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_1_nama']))
                    || (array_key_exists('komponen_' . $counter . '_' . $childCharCounter . '_2_nama', $dataBos) && !is_null($dataBos['komponen_' . $counter . '_' . $childCharCounter . '_2_nama']))
                );
            }
            $item['subkomponen'] = $childs;
            $result['komponen_penggunaan'][$counter - 1] = $item;
            $counter++;
            $komponenExist = array_key_exists('komponen_' . $counter, $dataBos) && !is_null($dataBos['komponen_' . $counter]);
        }

        return $result;
    }

    private function generateBosMadrasahDynamyc(array $dataRealisasiBos) {
        $result = $dataRealisasiBos;
        $result['komponen_penggunaan'] = [];
        $counter = 1;
        $komponenExist = array_key_exists('bos_real_komp_' . $counter, $dataRealisasiBos);
        while ($komponenExist) {
            $item = [];
            $item['nama'] = $this->namaKomponenBosMadrasah[$counter];
            $item['dana'] = $dataRealisasiBos['bos_real_komp_' . $counter];
            $childs = [];
            if(array_key_exists('bos_real_komp_' . $counter . '_biaya', $dataRealisasiBos)) {
                $childItem = [
                    'nama' => '',
                    'nama_unit' => '',
                    'nama_dana' => '',
                    'total_unit' => null,
                    'total_dana' => null
                ];
                $childItem['nama'] = "Biaya Komponen " . $counter;
                $childItem['total_dana'] = $dataRealisasiBos['bos_real_komp_' . $counter . '_biaya'];
                array_push($childs, $childItem);
            }
            $item['subkomponen'] = $childs;
            $result['komponen_penggunaan'][$counter - 1] = $item;
            $counter++;
            $komponenExist = array_key_exists('bos_real_komp_' . $counter, $dataRealisasiBos);
        }

        return $result;
    }

    private function prosesPencairan($result, $pencairan)
    {
        $result["dana_dari_provinsi"] = $pencairan["jumlah_dana"];
        $result["total_dana_tahap_ini"] = $pencairan["jumlah_dana"];
        $result["jumlah_pengurang"] = $pencairan["jumlah_pengurang"];
        $result["tanggal_cair"] = $pencairan["tanggal_sp2d"];
        $result["tanggal_cut_off"] = $pencairan["tanggal_cut_off"];
        $result["jumlah_siswa"] = $pencairan["jumlah_siswa"];
        $result["status_salur"] = $pencairan["status_salur"];
        $result["lapor_penggunaan"] = $pencairan["lapor_penggunaan"];
        $result["lapor_penggunaan_nama"] = $pencairan["lapor_penggunaan_nama"];
        $result["konfirmasi_sekolah"] = $pencairan["konfirmasi_sekolah"];
        $result["konfirmasi_sekolah_nama"] = $pencairan["konfirmasi_sekolah_nama"];
        return $result;
    }

    private function addSekolahInfo($res, $dataSource)
    {
        $res["sekolah_id"] = $dataSource["sekolah_id"];
        $res["nama_sekolah"] = $dataSource["nama_sekolah"];
        if (array_key_exists("status_sekolah", $dataSource) && $dataSource["status_sekolah"] == "N") {
            $res["status"] = "negeri";
        } else {
            $res["status"] = $this->getValue($dataSource, "status_sekolah") ?? $this->getValue($dataSource, "status");
        }
        $res["npsn"] = $this->getValue($dataSource, "npsn");
        $res["bentuk"] = $this->getValue($dataSource, "jenjang") ?? $this->getValue($dataSource, "bentuk");
        $res["triwulan"] = $this->getValue($dataSource, "triwulan");
        return $res;
    }

    public function getValue($array, $key)
    {
        return array_key_exists($key, $array) ? $array[$key] : null;
    }

    public function years()
    {
        $source = $this->request->getQuery('source', null, '');

        if (strtolower($source) == 'kemenag') {
            return new SimpleResponse([2019]);
        } else {
            /*try {
                $bosClient = new NeoBosClient($this->config["neo_bos_prop"]);
                $bosClient->setLogger($this->logger);
                $result = $bosClient->getYears();
                if ($result['message'] == 'Sukses') {
                    return new SimpleResponse(array_values($result['data']));
                } else {
                    return new SimpleResponse([2020, 2021, 2022, 2023]);
                }
            } catch (\Exception $e) {
                return new SimpleResponse([2020, 2021, 2022, 2023]);
            }*/
            return new SimpleResponse([2020, 2021, 2022, 2023, 2024, 2025, 2026]);
        }
    }

    public function daftarPenerima() {
        $request = $this->request->get();
        $request['limit'] = array_key_exists('limit', $request) ? $request['limit'] : 10;
        $request['offset'] = array_key_exists('offset', $request) ? $request['offset'] : 0;
        $validated = $this->validate($request, [
            'tahun' => ['validators' => ['digit']],
            'jenis_salur' => ['validators' => []],
            'npsn' => ['validators' => []],
            'limit' => ['validators' => ['required', 'digit']],
            'offset' => ['validators' => ['required', 'digit']]
        ]);

        $tahun = $validated['tahun'];
        $jenisSalur = $validated['jenis_salur'];
        $npsn = $validated['npsn'];
        $limit = $validated['limit'];
        $offset = $validated['offset'];
        $conditions = ["1=1"];
        $bind = [];
        if (!empty($tahun)) {
            array_push($conditions, "tahun = :tahun:");
            $bind["tahun"] = $tahun;
        }
        if (!empty($jenisSalur)) {
            array_push($conditions, "jenis_salur LIKE :jenis_salur:");
            $bind["jenis_salur"] = $jenisSalur;
        }
        if (!empty($npsn)) {
            array_push($conditions, "npsn LIKE :npsn:");
            $bind["npsn"] = $npsn;
        }

        $rows = PenerimaBos::find([
            "conditions" => implode(" AND ", $conditions),
            "bind" => $bind,
            "limit" => $limit,
            "offset" => $offset
        ]);

        $total = PenerimaBos::count([
            "conditions" => implode(" AND ", $conditions),
            "bind" => $bind,
        ]);

        return new PaginatedResponse($rows, $total, $limit, $offset);
    }

    public function bosYears()
    {
        $bosClient = new NeoBosClient($this->config["neo_bos_prop"]);
        $bosClient->setLogger($this->logger);

        $result = $bosClient->getTahun();

        if (array_key_exists('data', $result) && is_array($result['data'])) {
            return new SimpleResponse($result['data']);
        } else {
            $errorMessage = is_array($result) && array_key_exists('error', $result) ? $result['error'] : $bosClient->getErrorBody();
            $bosClient->apiLog->log_error("BOS", "no-params", $errorMessage);
            throw new CustomErrorException(BaseResponse::GUZZLE_ERROR, 'Gagal menghubungi server BOS KemenDikBud');
        }
    }
}
