<?php

use DusanKasan\Knapsack\Collection;
use LZCompressor\LZString;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Phalcon\Queue\Beanstalk;

class UtilityController extends BaseController
{
    public function adaptUsername()
    {
        AuthHelper::validateToolsKey($this->request, $this->config);
        $users = UmUser::find("um_user_name = email OR um_user_name is NULL");

        foreach ($users as $user) {
            $user->um_user_name = UserHelper::generateUsernameForEmail($user->email, $user->nama);
            $user->save();
        }

        return [
            'count' => count($users),
            'message' => 'Successfully update username'
        ];
    }

    public function test()
    {
    }

    public function adaptJenjangSekolah()
    {
        AuthHelper::validateToolsKey($this->request, $this->config);

        $queryUpdateEmptyJenjangId =
            'with t as (
                select s.id as id, s.bentuk, j.nama_jenjang as jenjang, j.id as jid
                from jaga.sekolah s join jaga.jenjang j on s.bentuk = j.nama_jenjang
                    where s.bentuk is not null and s.jenjang_id is null
            )
            update sekolah s
            set jenjang_id = t.jid
            from t
            where s.id = t.id';

        $connection = $this->db;
        $data = $connection->query($queryUpdateEmptyJenjangId);
        $data->setFetchMode(\Phalcon\Db::FETCH_ASSOC);
        $resultsEmptyJenjangId = count($data->fetchAll());

        $queryUpdateMismatchJenjangId =
            'with t as (
                select ps . id, ps . bentuk, ps . nama, j . nama_jenjang as jenjang, j . id as jid
                from(
                    SELECT s . id,
                    s . nama,
                    bentuk
                        FROM "jaga" . "sekolah" s join jaga . jenjang j on s . jenjang_id = j . id
                        where s . bentuk <> j . nama_jenjang
                ) as ps join jaga . jenjang j on ps . bentuk = j . nama_jenjang
            )
            update sekolah s
            set jenjang_id = t.jid
            from t
            where s.id = t.id';

        $data2 = $connection->query($queryUpdateMismatchJenjangId);
        $data2->setFetchMode(\Phalcon\Db::FETCH_ASSOC);
        $resultsMismatchJenjangId = count($data2->fetchAll());

        return [
            'update_empty_jenjang_id' => $resultsEmptyJenjangId,
            'update_mismatch_jenjang_id' => $resultsMismatchJenjangId
        ];
    }

    public function importKorsupgahUser()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile('document', ['text/csv', 'application/vnd.ms-excel']);

        $fails = [];

        if (!empty($document)) {
            $filename = $document['tmp_name'];
            $csv = array_map('str_getcsv', file($filename));
            array_shift($csv);
            $random = new \Phalcon\Security\Random();

            $roles = Roles::find([
                'conditions' => 'id in ({roles:array})',
                'bind' => ['roles' => [1, 16]] // Normal User & Bansos KLOP Korsupgah
            ]);

            foreach ($csv as $key => $row) {
                $old_user_id = $row[0];
                $nip = $row[1];
                $fullname = $row[2];
                $username = $row[3];
                $email = $row[4];
                $phone = $row[5];
                $password = $row[6];
                $klop_id = $row[7];

                $existing_users = UmUser::find([
                    'conditions' => 'lower(um_user_name)=:username: OR lower(email)=:email:',
                    'bind' => [
                        'username' => strtolower($username),
                        'email' => strtolower($email)
                    ]
                ]);

                if ($klop_id == "649") {
                    $row[] = "KPK!";
                    $fails[] = $row;
                } elseif (count($existing_users) > 0) {
                    $row[] = "Exists!";
                    $fails[] = $row;
                } else {
                    $hashed_password = base64_encode(hash("sha256", 'HelloWorld', true));

                    $generated_email = 'temp' . $random->hex(10) . '@jaga.id';
                    $validated_email = $email;
                    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
                        $validated_email = $generated_email;
                    }

                    $user = new UmUser();
                    $user->um_changed_time = date("Y-m-d H:i:s");
                    $user->um_tenant_id = -1234;
                    $user->um_user_korsupgah_password = $password;
                    $user->um_user_password = $hashed_password;
                    $user->nama = $fullname;
                    $user->email = $validated_email;
                    $user->um_user_name = $username;
                    $user->phone = $phone;
                    $user->no_ktp_sim = $nip;
                    if (!empty($klop_id)) {
                        $user->id_instansi = $klop_id;
                    }
                    $user->sumber = UmUser::SUMBER_KORSUPGAH;
                    $user->migration_status = UmUser::MIGRATION_STATUS_INIT;
                    $status = $user->save();

                    $user->setRoles2($roles);

                    if (!$status) {
                        $message = $user->getMessages()[0]->getMessage();
                        $row[] = $message;
                        $fails[] = $row;
                    }
                }
            }

            $result = [
                'fails_count' => count($fails),
                'fails' => $fails
            ];


            return new CollectionPaginatedResponse([$result]);
        } else {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found or Not active");
        }
    }

    public function importStranasUser()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile('document', ['text/csv', 'application/vnd.ms-excel']);

        $should_exists = [];
        $fails = [];

        if (!empty($document)) {
            $filename = $document['tmp_name'];

            $csv = new ParseCsv\Csv();
            $csv->parse($filename);

            $roles = Roles::find([
                'conditions' => 'id in ({roles:array})',
                'bind' => ['roles' => [1, 5]] // Normal User & Admin KLOP Stranas
            ]);

            foreach ($csv->data as $key => $row) {
                $existing_users = UmUser::find([
                    'conditions' => 'lower(um_user_name)=:username:',
                    'bind' => [
                        'username' => strtolower($row['username'])
                    ]
                ]);

                if (count($existing_users) > 0) {
                    $user = $existing_users[0];

                    // Case user baru: reset password + tandai bukan korsupgah
                    if (empty($row['sumber'])) {
                        $user->um_user_new_password = $this->security->hash($row['plain_password']);
                        $user->sumber = null;
                        $user->migration_status = null;
                    }

                    $user->um_user_name = $row['username'];
                    $user->email = $row['email'];
                    $user->id_instansi = $row['id_instansi'];

                    $user->save();
                } else {
                    // Harusnya user korsupgah ini sudah terdaftar
                    if (!empty($row['sumber'])) {
                        $should_exists[] = $row;
                    } else {
                        $old_format_password = base64_encode(hash("sha256", 'HelloWorld', true));
                        $new_format_password = $this->security->hash($row['plain_password']);

                        $user = new UmUser();
                        $user->um_changed_time = date("Y-m-d H:i:s");
                        $user->um_tenant_id = -1234;

                        $user->um_user_new_password = $new_format_password;
                        $user->um_user_password = $old_format_password;
                        $user->nama = $row['nama_instansi'];
                        $user->email = $row['email'];
                        $user->um_user_name = $row['username'];
                        $user->phone = "";
                        $user->no_ktp_sim = "";
                        $user->id_instansi = $row['id_instansi'];
                        $user->sumber = null;
                        $user->migration_status = null;
                        $status = $user->save();

                        $user->setRoles2($roles);

                        if (!$status) {
                            $message = $user->getMessages()[0]->getMessage();
                            $row[] = $message;
                            $fails[] = $row;
                        }
                    }
                }
            }

            $result = [
                'should_exists' => $should_exists,
                'fails' => $fails
            ];

            return new CollectionPaginatedResponse([$result]);
        } else {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found or Not active");
        }
    }

    public function importUser()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile('document', ['text/csv', 'application/vnd.ms-excel']);

        $fails = [];
        $success = [];

        $roleKeyValues = Roles::find()->toArray();
        $roleKeyValues = ArrayHelper::asKeyValue($roleKeyValues, 'name');

        if (!empty($document)) {
            $filename = $document['tmp_name'];
            $csv = array_map('str_getcsv', file($filename));
            array_shift($csv);
            $random = new \Phalcon\Security\Random();

            foreach ($csv as $key => $row) {
                $fullname = $row[0];
                $username = $row[2];
                $email = $row[3];
                $phone = $row[4];
                $password = $row[5];
                $role_ids = [];
                if(empty($row[1])) {
                    $role_ids = explode(",", $row[6]);
                } else {
                    $role_names = explode("|", $row[1]);
                    foreach ($role_names as $role_name) {
                        array_push($role_ids, $roleKeyValues[$role_name]['id']);
                    }
                }
                $id_instansi = null;

                if (count($row) > 7 && !empty($row[7])) {
                    $id_instansi = $row[7];
                }

                $existing_users = UmUser::find([
                    'conditions' => 'lower(um_user_name)=:username: OR lower(email)=:email:',
                    'bind' => [
                        'username' => strtolower($username),
                        'email' => strtolower($email)
                    ]
                ]);

                if (count($existing_users) > 0) {
                    $row[] = "Username atau email telah digunakan.";
                    $fails[] = $row;
                } else {
                    $hashed_password = base64_encode(hash("sha256", 'HelloWorld', true));

                    $generated_email = 'temp' . $random->hex(10) . '@jaga.id';
                    $validated_email = $email;
                    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
                        $validated_email = $generated_email;
                    }

                    $user = new UmUser();
                    $user->um_changed_time = date("Y-m-d H:i:s");
                    $user->um_tenant_id = -1234;
                    $user->um_user_password = $hashed_password;
                    $user->um_user_new_password = $this->security->hash($password);
                    $user->nama = $fullname;
                    $user->email = $validated_email;
                    $user->um_user_name = $username;
                    $user->phone = $phone;
                    $user->no_ktp_sim = '-';
                    $user->sumber = UmUser::SUMBER_IMPORT_CSV;
                    $user->id_instansi = $id_instansi;
                    $status = $user->save();

                    $roles = Roles::find([
                        'conditions' => 'id in ({roles:array})',
                        'bind' => ['roles' => $role_ids] // Normal User & Admin KLOP Stranas
                    ]);

                    $user->setRoles2($roles);

                    if (!$status) {
                        $message = $user->getMessages()[0]->getMessage();
                        $row[] = $message;
                        $fails[] = $row;
                    } else {
                        $row[] = "Berhasil ditambahkan.";
                        $success[] = $row;
                    }
                }
            }

            $result = [
                'fails_count' => count($fails),
                'fails' => $fails,
                'success_count' => count($success),
                'success' => $success
            ];

            return new CollectionPaginatedResponse([$result]);
        } else {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found or Not active");
        }
    }

    public function importKorsupgahKlop()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile('document', ['text/csv', 'application/vnd.ms-excel']);

        $fails = [];

        if (!empty($document)) {
            $filename = $document['tmp_name'];
            $csv = array_map('str_getcsv', file($filename));
            array_shift($csv);

            foreach ($csv as $key => $row) {
                $id = $row[0];
                $name = $row[1];
                $provinsi_id = $row[2];
                $kab_kota_id = $row[3];

                $instansi = new Instansi();
                $instansi->id = $id;
                $instansi->nama = $name;
                $instansi->id_provinsi = empty($provinsi_id) ? null : $provinsi_id;
                $instansi->id_kota_kabupaten = empty($kab_kota_id) ? null : $kab_kota_id;
                $instansi->sumber = Instansi::SUMBER_KORSUPGAH;
                $status = $instansi->save();

                $this->db->query("SELECT setval('instansi_id_seq', (SELECT MAX(id) FROM jaga.instansi));");

                usleep(20000); // Sleep 20 ms
                if (!$status) {
                    $message = $instansi->getMessages()[0]->getMessage();
                    $row[] = $message;
                    $fails[] = $row;
                }
            }

            $result = [
                'fails_count' => count($fails),
                'fails' => $fails
            ];

            return new CollectionPaginatedResponse([$result]);
        } else {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found or Not active");
        }
    }

    public function importStranasData()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile('document', ['text/csv', 'application/vnd.ms-excel']);

        $fails = [];

        if (!empty($document)) {
            $filename = $document['tmp_name'];
            $csv = new ParseCsv\Csv();
            $csv->parse($filename);

            $instansi_dictionary = Collection::from($csv->data)
                ->groupBy(function ($row) {
                    return $row['new_klop_id'];
                });

            // Daftarkan atau update semua instansi
            foreach ($instansi_dictionary as $instansi_id => $instansi_collection) {
                $instansi = Instansi::findFirst($instansi_id);
                $input = $instansi_collection->get(0);

                if (empty($instansi)) {
                    $instansi = new Instansi();
                    $instansi->id = $instansi_id;
                    $instansi->nama = $input['Klop_name'];
                } else {
                    $instansi->nama = $input['Klop_name'];
                }
                $instansi->save();

                $this->db->query("SELECT setval('instansi_id_seq', (SELECT MAX(id) FROM jaga.instansi));");

                usleep(40000); // Sleep 40 ms
            }

            $instansi_periode_dictionary = Collection::from($csv->data)
                ->groupBy(function ($row) {
                    return $row['new_klop_id'] . '-##-' . $row['periode'];
                });

            // Untuk setiap pasangan periode dan instansi:
            // 1. Buat survey
            // 2. Buat survey template
            // 3. Daftarkan pertanyaan/target pada survey template
            foreach ($instansi_periode_dictionary as $instansi_periode_string => $rows) {
                $temp = explode("-##-", $instansi_periode_string);
                $id_instansi = $temp[0];
                $periode_code = $temp[1];

                $periode = StranasPeriode::findFirstByNama($periode_code);
                $instansi = Instansi::findFirst($id_instansi);

                if (!empty($instansi) && !empty($periode)) {
                    // Pastikan survey dan survey template ada
                    $survey_list = StranasSurvey::query()
                        ->where('id_periode = :id_periode:')
                        ->andWhere('id_instansi_satker = :id_instansi_satker:')
                        ->bind([
                            'id_periode' => $periode->id,
                            'id_instansi_satker' => $instansi->id
                        ])
                        ->execute();

                    $survey = null;
                    $survey_template = null;

                    if (count($survey_list) < 1) {
                        $survey_template = new StranasSurveyTemplate();
                        $survey_template->nama = $instansi->nama . ' - ' . $periode_code;
                        $survey_template->created_by = $this->shared->user->um_id;
                        $survey_template->save();

                        usleep(20000); // Sleep 20 ms

                        $survey = new StranasSurvey();
                        $survey->id_periode = $periode->id;
                        $survey->id_instansi_satker = $instansi->id;
                        $survey->id_survey_template = $survey_template->id;
                        $survey_template->created_by = $this->shared->user->um_id;
                        $survey->save();

                        usleep(20000); // Sleep 20 ms
                    } else {
                        $survey = $survey_list[0];
                        $survey_template = $survey->stranasSurveyTemplate;
                    }

                    $stranas_data_list = $rows->toArray();

                    $target_count = 0;

                    // Daftarkan pertanyaan/target ke dalam survey template
                    foreach ($stranas_data_list as $key => $stranas_data) {
                        $keterangan = trim(preg_replace('/[^[:print:]]/', '', $stranas_data['trgPer']));
                        $info_lampiran = trim(preg_replace('/[^[:print:]]/', '', $stranas_data['dd']));
                        $info_nilai = trim(preg_replace('/[^[:print:]]/', '', $stranas_data['kuca']));

                        if (!empty($keterangan . $info_lampiran . $info_nilai) && strlen($keterangan) > 10) {
                            $target_list = StranasTarget::find([
                                'conditions' => 'keterangan = :keterangan: AND info_nilai = :info_nilai: AND info_lampiran = :info_lampiran: AND id_ukuran_keberhasilan=:id_ukuran_keberhasilan:',
                                'bind' => [
                                    'id_ukuran_keberhasilan' => $stranas_data['uk_id'],
                                    'keterangan' => $keterangan,
                                    'info_nilai' => $info_nilai,
                                    'info_lampiran' => $info_lampiran
                                ]
                            ]);
                            $target = null;

                            if (count($target_list) < 1) {
                                $target = new StranasTarget();
                                $target->id_ukuran_keberhasilan = $stranas_data['uk_id'];
                                $target->keterangan = $keterangan;
                                $target->info_nilai = $info_nilai;
                                $target->info_lampiran = $info_lampiran;
                                $target->created_by = $this->shared->user->um_id;
                                $target->save();
                                usleep(20000); // Sleep 20 ms
                            } else {
                                $target = $target_list[0];
                            }

                            $records = StranasSurveyTemplateQuestion::find([
                                'conditions' => 'id_survey_template=:id_survey_template: AND id_target=:id_target:',
                                'bind' => [
                                    'id_survey_template' => $survey_template->id,
                                    'id_target' => $target->id
                                ]
                            ]);

                            if (count($records) < 1) {
                                $survey_template_question = new StranasSurveyTemplateQuestion();
                                $survey_template_question->id_survey_template = $survey_template->id;
                                $survey_template_question->id_target = $target->id;
                                $survey_template_question->created_by = $this->shared->user->um_id;
                                $survey_template_question->save();
                            }

                            $target_count++;
                        }
                    }

                    if ($target_count < 1) {
                        if (empty($survey) || empty($survey_template)) {
                            $hello = "World";
                            echo "Why";
                        } else {
                            $survey->delete();
                            $survey_template->delete();
                        }
                    }
                }
            }

            return new CollectionPaginatedResponse([]);
        } else {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found or Not active");
        }
    }

    public function export_diskusi()
    {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);
        $mode = $this->request->get('mode');

        if (empty($mode)) {
            // Use strip php
            $mode = 1;
        }

        $query = '
        SELECT
        d.id as diskusi_id,
        d.created_at as diskusi_created_at,
        p.nama as sektor,
        "dob".nama_objek as objek_nama,
        "dob".objek_id as objek_id,
        d."type",
        d.title as diskusi_title,
        d.content as diskusi_content,
        d.is_deleted as diskusi_deleted,
        u.um_user_name as diskusi_creator,
        c.id as comment_id,
        c.created_at as comment_created_at,
        c."comment" as comment_content,
        uc.um_user_name as commentator,
        c.is_deleted as comment_deleted
    FROM "jaga"."diskusi" d
        left outer join diskusi_comment c on c.diskusi_id = d.id
        join "public".um_user u on d.user_id = u.um_id
      left outer join "public".um_user uc on c.user_id = uc.um_id
      join kategori_diskusi kd on d.kategori_diskusi_id = kd.id
      join produk p on kd.produk_id = p.id_index
        left outer join diskusi_objek dob on dob.diskusi_id = d.id
    order by diskusi_id, comment_id ;
        ';

        $result = $this->rawQuery($query, []);

        $header = [
            "diskusi_id",
            "diskusi_created_at",
            "sektor",
            "objek_nama",
            "objek_id",
            "type",
            "diskusi_title",
            "diskusi_content",
            "diskusi_deleted",
            "diskusi_creator",
            "comment_id",
            "comment_created_at",
            "comment_content",
            "commentator",
            "comment_deleted"
        ];
        $rows = [];
        $rows[] = $header;
        foreach ($result as $index => $data) {
            $diskusi_content = $data['diskusi_content'];
            $comment_content = $data['comment_content'];

            if ($mode == 1) {
                try {
                    $diskusi_content = strip_tags($data['diskusi_content']);
                } catch (Exception $e) {
                    $ress = 1;
                }
                try {
                    $comment_content = strip_tags($data['comment_content']);
                } catch (Exception $e) {
                    $ress = 1;
                }
            } else {
                try {
                    $diskusi_content = \Soundasleep\Html2Text::convert($data['diskusi_content']);
                } catch (Exception $e) {
                    $ress = 1;
                }
                try {
                    $comment_content = \Soundasleep\Html2Text::convert($data['comment_content']);
                } catch (Exception $e) {
                    $ress = 1;
                }
            }

            $rows[] = [
                $data['diskusi_id'],
                $data['diskusi_created_at'],
                $data['sektor'],
                $data['objek_nama'],
                $data['objek_id'],
                $data['type'],
                $data['diskusi_title'],
                $diskusi_content,
                $data['diskusi_deleted'],
                $data['diskusi_creator'],
                $data['comment_id'],
                $data['comment_created_at'],
                $comment_content,
                $data['commentator'],
                $data['comment_deleted']
            ];
        }
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->fromArray($rows, null, 'A1');

        $writer = new Xlsx($spreadsheet);
        $writer->setPreCalculateFormulas(false);
        $filename = "export_diskusi_" . date('Ymd') . ".xls";
        header('Content-type: application/vnd.ms-excel');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        $writer->save('php://output');
    }

    public function notifySelf()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $rawParams = $this->request->get();
        $params = $this->validate(
            $rawParams,
            [
                'message' => ['validators' => ['required']],
                'message_en' => ['validators' => ['required']],
                'action' => ['validators' => ['required']],
                'actionId' => ['validators' => ['required']],
                'category' => ['validators' => ['required']]
            ]
        );

        $uuid = $this->shared->user->um_id;

        NotificationHelper::send($uuid, $uuid, $params["message"], $params["action"], $params["actionId"], '', $params['category'], $params["message_en"]);

        return new SimpleResponse("OK");
    }

    public function notifyMulticast()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $rawParams = json_decode(json_encode($this->request->getJsonRawBody()), true);;
        $rawParams = array_merge($rawParams, $this->request->get());
        $params = $this->validate(
            $rawParams,
            [
                'message' => ['validators' => ['required']],
                'action' => ['validators' => ['required']],
                'actionId' => ['validators' => ['required']],
                'category' => ['validators' => ['required']],
                'userIds' => ['validators' => ['required']]
            ]
        );

        $uuid = $this->shared->user->um_id;

        NotificationHelper::sendMulticast($params['userIds'], $uuid, $params["message"], $params["action"], $params["actionId"], '', $params['category']);

        return new SimpleResponse("OK");
    }

    public function testMail()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        $mailHelper = new MailHelper($this->config['mail_config']);
        $mailHelper->sendMail('robethrahmatullah@gmail.com', 'Test mail ' . rand(), 'Test message');

        return new SimpleResponse("OK");
    }

    public function testOmspanPenyerapanDanaDesa($kodeLokasi)
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);

        if (strlen($kodeLokasi) != 4) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Kode lokasi harus 4 digit dan menunjukan lokasi sesuai kode pemda versi omspan");
        }

        $desaClient = new DesaClient($this->config["desa_prop"]);
        $desaClient->setLogger($this->logger);
        $desaClient->penyerapanDanaDesa(2019, substr($kodeLokasi, 0, 2), $kodeLokasi);
        if ($desaClient->getObjectsProcessed() == 1) {
            $additionalData = [
                "objects_processed" => "Tidak Ada Data"
            ];
        } else {
            $additionalData = [
                "objects_processed" => $desaClient->getObjectsProcessed()
            ];
        }

        return new SimpleResponse([
            'start' => $desaClient->getStartTime(),
            'end' => $desaClient->getEndTime(),
            'data' => $additionalData
        ]);
    }

    public function notifyBlockingQueueBeanstalk()
    {
        $this->checkScopes(['admin.view']);

        $apiLog = new ApiErrorsService($this->config);
        $message = $apiLog->process_notif_job();
        return $message;
    }

    public function bpjsSignature()
    {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $defaultTimezone = date_default_timezone_get();
        date_default_timezone_set('UTC');
        $timestamp = strval(time() - strtotime('1970-01-01 00:00:00'));
        if ($defaultTimezone != 'UTC') date_default_timezone_set($defaultTimezone);

        $secretKey = getenv("BPJS2_SECRET_KEY");
        $consid = getenv("BPJS2_CONS_ID");
        $hash = hash_hmac("sha256", $consid . "&" . $timestamp, $secretKey, true);
        $signature = base64_encode($hash);

        return new SimpleResponse([
            "timestamp" => $timestamp,
            "signature" => $signature
        ]);
    }

    public function bpjsDecrypt()
    {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $rawBody = $this->request->getJsonRawBody(true);
        $params = $this->validate(
            $rawBody,
            [
                'string' => ['required'],
                'timestamp' => ['required'],
            ]
        );

        try {
            $encrypt_method = 'AES-256-CBC';

            $consid = getenv("BPJS2_CONS_ID");
            $conspwd = getenv("BPJS2_SECRET_KEY");
            $timestamp = $params['timestamp'];

            $string = $params['string'];

            $signature = $consid . $conspwd . $timestamp;

            // hash
            $key = hex2bin(hash('sha256', $signature));

            // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
            $iv = substr(hex2bin(hash('sha256', $signature)), 0, 16);

            $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, OPENSSL_RAW_DATA, $iv);
            $dOutput = LZString::decompressFromEncodedURIComponent($output);
        }
        catch (\Exception $e) {
            print_r($e->getMessage());
        }

        return new SimpleResponse(json_decode($dOutput));
    }

    public function bpjsStatKapitasi() {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $response = [];

        $puskesmas = BpjsPuskesmas::find([
            'columns' => 'COUNT(*)'
        ])[0];
        $response['jumlah_puskemas'] = $puskesmas->toArray()[0];

        $puskesmas = BpjsPuskesmas::find([
            'columns' => 'COUNT(*)',
            'conditions' => 'last_update_kapitasi IS NULL OR last_update_kapitasi <= ?0',
            'bind' => [
                date('Y-m-d', strtotime('-' . Bpjs2Client::FILTER_LAST_UPDATE . ' day'))
            ]
        ])[0];
        $response['jumlah_puskemas_belum_update_kapitasi'] = $puskesmas->toArray()[0];

        $kapitasi = BpjsPuskesmasKapitasi::find([
            'columns' => 'COUNT(*)'
        ])[0];
        $response['jumlah_kapitasi'] = $kapitasi->toArray()[0];

        $kapitasi = BpjsPuskesmasKapitasi::find([
            'columns' => 'COUNT(DISTINCT(kodepuskesmas))',
        ])[0];
        $response['jumlah_kapitasi_puskesmas'] = $kapitasi->toArray()[0];

        return new SimpleResponse($response);
    }

    public function importKorsupgahSubIndikator() {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile('document', ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);

        if (!empty($document)) {
            $filename = $document['tmp_name'];
            $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
            $worksheet = $spreadsheet->getActiveSheet();
            $subIndikators = [];
            $currentMaxRowC = 0;
            $currentareaintervensi = $currentindikator = $currentsubindikator = $infolampiran = $infonilai = "";
            foreach ($worksheet->getRowIterator() as $row) {
                $celliterator = $row->getCellIterator();
                $celliterator->setIterateOnlyExistingCells(false);
                foreach ($celliterator as $cell) {
                    $row = $cell->getRow();
                    if ($row > 1) {
                        $column = $cell->getColumn();
                        $text = $cell->getFormattedValue();
                        if ($column == 'A' && $text != "") {
                            $currentareaintervensi = $text;
                        } else if ($column == 'B' && $text != "") {
                            $currentindikator = $text;
                        } else if ($column == 'C') {
                            $mergerange = $cell->getMergeRange();
                            if ($mergerange) {
                                $maxRowC = substr(explode(':', $mergerange)[1], 1);
                                if ($maxRowC == $row) {
                                    if ($currentsubindikator != "") {
                                        $subIndikator = [
                                            'areaintervensi' => $currentareaintervensi,
                                            'indikator' => $currentindikator,
                                            'subindikator' => $currentsubindikator,
                                            'info_lampiran' => $infolampiran,
                                            'info_nilai' => $infonilai
                                        ];
                                        array_push($subIndikators, $subIndikator);
                                        $currentsubindikator = $infolampiran = $infonilai = "";
                                    }
                                }
                                if ($maxRowC > $currentMaxRowC) {
                                    $currentMaxRowC = $maxRowC;
                                    if ($text != "") $currentsubindikator .= $text;
                                }
                            }
                        }else if ($column == 'D' && $text != "") {
                            $infolampiran .= $text . "\n";
                        } else if ($column == 'E' && $text != "") {
                            $infonilai .= $text . "\n";
                        }
                    }
                }
            }

            $queries = [];
            foreach ($subIndikators as $subIndikator) {
                $infoLampiran = $subIndikator['info_lampiran'];
                $infoNilai = $subIndikator['info_nilai'];
                $nama = $subIndikator['subindikator'];
                $indikator = $subIndikator['indikator'];
                $areaintervensi = $subIndikator['areaintervensi'];

                $q = "update jaga.korsupgah_sub_indikator set info_lampiran = E'".trim($infoLampiran)."', info_nilai = E'".trim($infoNilai)."' where nama like '".trim($nama)."' and id_indikator = (select id from jaga.korsupgah_indikator where nama like '".trim($indikator)."' and id_area_intervensi = (select id from jaga.korsupgah_area_intervensi where nama like '".trim($areaintervensi)."' and keterangan like 'MCP-2022-%'))";
                array_push($queries, $q);
            }

            return new CollectionPaginatedResponse([$queries]);
        } else {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found or Not active");
        }
    }

    public function exportAdministrasiKorsupgah()
    {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $templateId = $this->request->get('template_id', null, 0);

        $template = KorsupgahTemplate::findFirst($templateId);
        if (!$template) throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "Template dengan ID [" . $templateId . "] tidak ditemukan!");

        $rows = $this->rawQuery("
            SELECT
                ai.id as ai_id,
                ai.nama as ai_nama,
                ai.keterangan as ai_keterangan,
                ai.presentase_bobot as ai_presentase_bobot,
                ai.presentase_bobot_wo_dana_desa as ai_presentase_bobot_wo_dana_desa,
                i.id as i_id,
                i.nama as i_nama,
                i.presentase_bobot as i_presentase_bobot,
                si.id as si_id,
                si.nama as si_nama,
                si.presentase_bobot as si_presentase_bobot,
                si.info_nilai as si_info_nilai,
                si.info_lampiran as si_info_lampiran   
            FROM
                korsupgah_template_sub_indikator ktsi
            LEFT JOIN korsupgah_sub_indikator si ON si.id = ktsi.id_sub_indikator
            LEFT JOIN korsupgah_indikator i ON i.id = si.id_indikator
            LEFT JOIN korsupgah_area_intervensi ai ON ai.id = i.id_area_intervensi
            WHERE ktsi.id_template = :template_id
            ORDER BY ai_id, i_id, si_id ASC
        ", ['template_id' => $templateId]);

        $result = [];
        foreach ($rows as $row) {
            $aiId = $row['ai_id'];
            $iId = $row['i_id'];
            $siId = $row['si_id'];

            $result[$aiId]['nama'] = $row['ai_nama'];
            $result[$aiId]['keterangan'] = $row['ai_keterangan'];
            $result[$aiId]['bobot'] = $row['ai_presentase_bobot'];
            $result[$aiId]['bobot_wo_dana_desa'] = $row['ai_presentase_bobot_wo_dana_desa'];

            if (!array_key_exists('indikator', $result[$aiId])) $result[$aiId]['indikator'] = [];
            if (!array_key_exists($iId, $result[$aiId]['indikator'])) $result[$aiId]['indikator'][$iId] = [];
            $result[$aiId]['indikator'][$iId]['nama'] = $row['i_nama'];
            $result[$aiId]['indikator'][$iId]['bobot'] = $row['i_presentase_bobot'];

            if (!array_key_exists('subindikator', $result[$aiId]['indikator'][$iId])) $result[$aiId]['indikator'][$iId]['subindikator'] = [];
            if (!array_key_exists($siId, $result[$aiId]['indikator'][$iId]['subindikator'])) $result[$aiId]['indikator'][$iId]['subindikator'][$siId] = [];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['nama'] = $row['si_nama'];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['bobot'] = $row['si_presentase_bobot'];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['info_nilai'] = $row['si_info_nilai'];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['info_lampiran'] = $row['si_info_lampiran'];
        }

        return $this->generateExcelAdministrasiKorsupgah($result, "Administrasi Korsupgah - ".$template->nama.".xlsx", "$template->nama");
    }

    public function downloadTemplateAdministrasiKorsupgah()
    {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $templateId = $this->request->get('template_id', null, 0);

        $template = KorsupgahTemplate::findFirst($templateId);
        if (!$template) throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "Template dengan ID [" . $templateId . "] tidak ditemukan!");

        $rows = $this->rawQuery("
            SELECT
                ai.id as ai_id,
                ai.nama as ai_nama,
                ai.keterangan as ai_keterangan,
                ai.presentase_bobot as ai_presentase_bobot,
                ai.presentase_bobot_wo_dana_desa as ai_presentase_bobot_wo_dana_desa,
                i.id as i_id,
                i.nama as i_nama,
                i.presentase_bobot as i_presentase_bobot,
                si.id as si_id,
                si.nama as si_nama,
                si.presentase_bobot as si_presentase_bobot,
                si.info_nilai as si_info_nilai,
                si.info_lampiran as si_info_lampiran
            FROM
                korsupgah_template_sub_indikator ktsi
            LEFT JOIN korsupgah_sub_indikator si ON si.id = ktsi.id_sub_indikator
            LEFT JOIN korsupgah_indikator i ON i.id = si.id_indikator
            LEFT JOIN korsupgah_area_intervensi ai ON ai.id = i.id_area_intervensi
            WHERE ktsi.id_template = :template_id
            ORDER BY ai_id, i_id, si_id ASC
        ", ['template_id' => $templateId]);

        $result = [];
        foreach ($rows as $row) {
            $aiId = $row['ai_id'];
            $iId = $row['i_id'];
            $siId = $row['si_id'];

            $result[$aiId]['nama'] = $row['ai_nama'];
            $result[$aiId]['keterangan'] = $row['ai_keterangan'];
            $result[$aiId]['bobot'] = $row['ai_presentase_bobot'];
            $result[$aiId]['bobot_wo_dana_desa'] = $row['ai_presentase_bobot_wo_dana_desa'];

            if (!array_key_exists('indikator', $result[$aiId])) $result[$aiId]['indikator'] = [];
            if (!array_key_exists($iId, $result[$aiId]['indikator'])) $result[$aiId]['indikator'][$iId] = [];
            $result[$aiId]['indikator'][$iId]['nama'] = $row['i_nama'];
            $result[$aiId]['indikator'][$iId]['bobot'] = $row['i_presentase_bobot'];

            if (!array_key_exists('subindikator', $result[$aiId]['indikator'][$iId])) $result[$aiId]['indikator'][$iId]['subindikator'] = [];
            if (!array_key_exists($siId, $result[$aiId]['indikator'][$iId]['subindikator'])) $result[$aiId]['indikator'][$iId]['subindikator'][$siId] = [];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['nama'] = $row['si_nama'];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['bobot'] = $row['si_presentase_bobot'];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['info_nilai'] = $row['si_info_nilai'];
            $result[$aiId]['indikator'][$iId]['subindikator'][$siId]['info_lampiran'] = $row['si_info_lampiran'];
        }
        $row = [];
        $row[array_keys($result)[0]] = $result[array_keys($result)[0]];
        return $this->generateExcelAdministrasiKorsupgah($row, "Template Administrasi Korsupgah.xlsx", "");
    }

    public function importAdministrasiKorsupgah()
    {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile2('document', ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], $this->request->getUploadedFiles());

        if (!empty($document)) {
            $filename = $document->getTempName();
            $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
            $worksheet = $spreadsheet->getActiveSheet();
            $data = [];
            $aiRow = 0;
            $iRow = 0;
            $siRow = 0;
            foreach ($worksheet->getRowIterator() as $row) {
                $celliterator = $row->getCellIterator();
                $celliterator->setIterateOnlyExistingCells(false);
                foreach ($celliterator as $cell) {
                    $row = $cell->getRow();
                    if ($row > 5) {
                        $column = $cell->getColumn();
                        $text = $cell->getFormattedValue();
                        if ($text != '') {
                            switch ($column) {
                                case 'A':
                                    $aiRow = $text;
                                    break;
                                case 'B':
                                    if (!array_key_exists($aiRow, $data)) $data[$aiRow] = ['ai' => [], 'indikators' => []];
                                    $data[$aiRow]['ai']['nama'] = $text;
                                    break;
                                case 'C':
                                    $data[$aiRow]['ai']['keterangan'] = $text;
                                    break;
                                case 'D':
                                    $data[$aiRow]['ai']['presentase_bobot'] = $text;
                                    break;
                                case 'E':
                                    $data[$aiRow]['ai']['presentase_bobot_wo_dana_desa'] = $text;
                                    break;
                                case 'F':
                                    $iRow = $text;
                                    break;
                                case 'G':
                                    if(!array_key_exists($iRow, $data[$aiRow]['indikators'])) $data[$aiRow]['indikators'][$iRow] = ['i' => [], 'subindikators' => []];
                                    $data[$aiRow]['indikators'][$iRow]['i']['nama'] = $text;
                                    break;
                                case 'H':
                                    $data[$aiRow]['indikators'][$iRow]['i']['presentase_bobot'] = $text;
                                    break;
                                case 'I':
                                    $siRow = $text;
                                    break;
                                case 'J':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['nama'] = $text;
                                    break;
                                case 'K':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['presentase_bobot'] = $text;
                                    break;
                                case 'L':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['info_nilai'] = $text;
                                    break;
                                case 'M':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['info_lampiran'] = $text;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }

            $this->db->begin();
            $aiId = $iId = $siId = 0;
            try{
                foreach ($data as $item) {
                    $ai = new KorsupgahAreaIntervensi();
                    $ai->assign($item['ai']);
                    $ai->save();
                    $aiId++;

                    $iBobot = 0;
                    foreach ($item['indikators'] as $indikator) {
                        $i = new KorsupgahIndikator();
                        $i->assign($indikator['i']);
                        $i->id_area_intervensi = $ai->id;
                        $i->id_tipe = 1;
                        $i->save();
                        $iId++;
                        $iBobot += $i->presentase_bobot;

                        $siBobot = 0;
                        foreach ($indikator['subindikators'] as $subindikator) {
                            $si = new KorsupgahSubIndikator();
                            $si->assign($subindikator['si']);
                            $si->id_indikator = $i->id;
                            $si->save();
                            $siId++;
                            $siBobot += $si->presentase_bobot;
                        }
                        if ($siBobot != 100) throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Total Bobot Subindikator Indikator[".$ai->nama."][".$i->nama."] kurang/lebih dari 100!");
                    }
                    if ($iBobot != 100) throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Total Bobot Indikator Area Intervensi[".$ai->nama."] kurang/lebih dari 100!");
                }
                $this->db->commit();
            } catch (\Exception $e) {
                $this->db->rollback();
                throw $e;
            }

            return new SimpleResponse([
                'jumlah_area_intervensi' => $aiId,
                'jumlah_indikator' => $iId,
                'jumlah_subindikator' => $siId
            ]);
        }
    }

    public function bulkUpdateAdministrasiKorsupgah() {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);

        $document = $this->getAndValidateImportFile2('document', ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], $this->request->getUploadedFiles());

        if (!empty($document)) {
            $filename = $document->getTempName();
            $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
            $worksheet = $spreadsheet->getActiveSheet();
            $data = [];
            $aiRow = 0;
            $iRow = 0;
            $siRow = 0;
            foreach ($worksheet->getRowIterator() as $row) {
                $celliterator = $row->getCellIterator();
                $celliterator->setIterateOnlyExistingCells(false);
                foreach ($celliterator as $cell) {
                    $row = $cell->getRow();
                    if ($row > 5) {
                        $column = $cell->getColumn();
                        $text = $cell->getFormattedValue();
                        if ($text != '') {
                            switch ($column) {
                                case 'A':
                                    $aiRow = $text;
                                    break;
                                case 'B':
                                    if (!array_key_exists($aiRow, $data)) $data[$aiRow] = ['ai' => [], 'indikators' => []];
                                    $data[$aiRow]['ai']['id'] = $aiRow;
                                    $data[$aiRow]['ai']['nama'] = $text;
                                    break;
                                case 'C':
                                    $data[$aiRow]['ai']['keterangan'] = $text;
                                    break;
                                case 'D':
                                    $data[$aiRow]['ai']['presentase_bobot'] = $text;
                                    break;
                                case 'E':
                                    $data[$aiRow]['ai']['presentase_bobot_wo_dana_desa'] = $text;
                                    break;
                                case 'F':
                                    $iRow = $text;
                                    break;
                                case 'G':
                                    if(!array_key_exists($iRow, $data[$aiRow]['indikators'])) $data[$aiRow]['indikators'][$iRow] = ['i' => [], 'subindikators' => []];
                                    $data[$aiRow]['indikators'][$iRow]['i']['id'] = $iRow;
                                    $data[$aiRow]['indikators'][$iRow]['i']['nama'] = $text;
                                    break;
                                case 'H':
                                    $data[$aiRow]['indikators'][$iRow]['i']['presentase_bobot'] = $text;
                                    break;
                                case 'I':
                                    $siRow = $text;
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['id'] = $siRow;
                                    break;
                                case 'J':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['nama'] = $text;
                                    break;
                                case 'K':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['presentase_bobot'] = $text;
                                    break;
                                case 'L':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['info_nilai'] = $text;
                                    break;
                                case 'M':
                                    $data[$aiRow]['indikators'][$iRow]['subindikators'][$siRow]['si']['info_lampiran'] = $text;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }

            $this->db->begin();
            $aiId = $iId = $siId = 0;
            try{
                foreach ($data as $item) {
                    $ai = KorsupgahAreaIntervensi::findFirst($item['ai']['id']);
                    if (!$ai) throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "Area Intervensi dengan id [" . $item['si']['id'] . "] tidak ditemukan");
                    $ai->assign($item['ai']);
                    $ai->save();
                    $aiId++;

                    $iBobot = 0;
                    foreach ($item['indikators'] as $indikator) {
                        $i = KorsupgahIndikator::findFirst($indikator['i']['id']);
                        if (!$i) throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "Indikator dengan id [" . $indikator['i']['id'] . "] tidak ditemukan");
                        $i->assign($indikator['i']);
                        $i->save();
                        $iId++;
                        $iBobot += $i->presentase_bobot;

                        $siBobot = 0;
                        foreach ($indikator['subindikators'] as $subindikator) {
                            $si = KorsupgahSubIndikator::findFirst($subindikator['si']['id']);
                            if (!$si) throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "Subindikator dengan id [" . $subindikator['si']['id'] . "] tidak ditemukan");
                            $si->assign($subindikator['si']);
                            $si->save();
                            $siId++;
                            $siBobot += $si->presentase_bobot;
                        }
                        if ($siBobot != 100) throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Total Bobot Subindikator Indikator[".$ai->nama."][".$i->nama."] kurang/lebih dari 100!");
                    }
                    if ($iBobot != 100) throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Total Bobot Indikator Area Intervensi[".$ai->nama."] kurang/lebih dari 100!");
                }
                $this->db->commit();
            } catch (\Exception $e) {
                $this->db->rollback();
                throw $e;
            }

            return new SimpleResponse([
                'jumlah_area_intervensi' => $aiId,
                'jumlah_indikator' => $iId,
                'jumlah_subindikator' => $siId
            ]);
        }
    }

    private function generateExcelAdministrasiKorsupgah($rows, $filename, $templateName = '')
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        $sheet->setCellValue("A1", 'Administrasi Korsupgah');
        $sheet->setCellValue("A2", $templateName);

        $sheet->getStyle('A1:A2')
            ->getAlignment()
            ->setHorizontal(Alignment::HORIZONTAL_CENTER);
        $sheet->mergeCells('A1:J1');
        $sheet->mergeCells('A2:J2');

        $sheet->setCellValue("A4", 'AREA INTERVENSI');
        $sheet->setCellValue("A5", 'ID');
        $sheet->setCellValue("B5", 'NAMA');
        $sheet->setCellValue("C5", 'KETERANGAN');
        $sheet->setCellValue("D5", 'BOBOT');
        $sheet->setCellValue("E5", 'BOBOT TANPA DANA DESA');
        $sheet->mergeCells('A4:E4');

        $sheet->setCellValue("F4", 'INDIKATOR');
        $sheet->setCellValue("F5", 'ID');
        $sheet->setCellValue("H5", 'NAMA');
        $sheet->setCellValue("H5", 'BOBOT');
        $sheet->mergeCells('F4:H4');

        $sheet->setCellValue("I4", 'SUBINDIKATOR');
        $sheet->setCellValue("I5", 'ID');
        $sheet->setCellValue("J5", 'NAMA');
        $sheet->setCellValue("K5", 'BOBOT');
        $sheet->setCellValue("L5", 'INFO NILAI');
        $sheet->setCellValue("M5", 'INFO LAMPIRAN');
        $sheet->mergeCells('I4:M4');

        $index = 6;
        foreach ($rows as $aiId => $areaintervensi) {
            $aiStart = $index;
            $sheet->setCellValue("A$index", $aiId);
            $sheet->setCellValue("B$index", $areaintervensi['nama']);
            $sheet->setCellValue("C$index", $areaintervensi['keterangan']);
            $sheet->setCellValue("D$index", $areaintervensi['bobot']);
            $sheet->setCellValue("E$index", $areaintervensi['bobot_wo_dana_desa']);
            foreach ($areaintervensi['indikator'] as $iId => $indikator) {
                $iStart = $index;
                $sheet->setCellValue("F$index", $iId);
                $sheet->setCellValue("G$index", $indikator['nama']);
                $sheet->setCellValue("H$index", $indikator['bobot']);
                foreach ($indikator['subindikator'] as $siId => $subindikator) {
                    $sheet->setCellValue("I$index", $siId);
                    $sheet->setCellValue("J$index", $subindikator['nama']);
                    $sheet->setCellValue("K$index", $subindikator['bobot']);
                    $sheet->setCellValue("L$index", $subindikator['info_nilai']);
                    $sheet->setCellValue("M$index", $subindikator['info_lampiran']);
                    $index++;
                }
                $iEnd = $index - 1;
                $sheet->getStyle("F$iStart:H$iEnd")
                    ->getAlignment()
                    ->setVertical(Alignment::VERTICAL_TOP);
                $sheet->mergeCells("F$iStart:F$iEnd");
                $sheet->mergeCells("G$iStart:G$iEnd");
                $sheet->mergeCells("H$iStart:H$iEnd");
            }
            $aiEnd = $index - 1;
            $sheet->getStyle("A$aiStart:E$aiEnd")
                ->getAlignment()
                ->setVertical(Alignment::VERTICAL_TOP);
            $sheet->mergeCells("A$aiStart:A$aiEnd");
            $sheet->mergeCells("B$aiStart:B$aiEnd");
            $sheet->mergeCells("C$aiStart:C$aiEnd");
            $sheet->mergeCells("D$aiStart:D$aiEnd");
            $sheet->mergeCells("E$aiStart:E$aiEnd");
        }

        $sheet->getColumnDimension('A')->setAutoSize(true);
        $sheet->getColumnDimension('B')->setAutoSize(true);
        $sheet->getColumnDimension('C')->setAutoSize(true);
        $sheet->getColumnDimension('D')->setAutoSize(true);
        $sheet->getColumnDimension('E')->setAutoSize(true);
        $sheet->getColumnDimension('F')->setAutoSize(true);
        $sheet->getColumnDimension('G')->setAutoSize(true);
        $sheet->getColumnDimension('H')->setAutoSize(true);
        $sheet->getColumnDimension('I')->setAutoSize(true);
        $sheet->getColumnDimension('J')->setAutoSize(true);
        $sheet->getColumnDimension('K')->setAutoSize(true);

        $styleArray = [
            'borders' => [
                'allBorders' => [
                    'borderStyle' => Border::BORDER_THIN,
                    'color' => ['argb' => 'FF000000'],
                ],
            ],
        ];

        $sheet->getStyle('A4:M' . ($index - 1))->applyFromArray($styleArray);

        $writer = new Xlsx($spreadsheet);
        header('Content-type: application/vnd.ms-excel');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        return $writer->save('php://output');
    }

    public function getTransaksiBakum() {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);
        $params = $this->request->get();
        $params = $this->validate($params, [
            'namabadanhukum' => ['validators' => ['required']]
        ]);

        $client = new AhuClient([
            "server" => "http://10.102.1.23"
        ]);
        $client->setLogger($this->logger);
        $res = $client->getTransaksiBakum($params['namabadanhukum']);

        return new SimpleResponse($res);
    }
    public function getTransaksiBakumP() {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);
        $params = $this->request->get();
        $params = $this->validate($params, [
            'namabadanhukum' => ['validators' => ['required']]
        ]);

        $client = new AhuClient([
            "server" => "http://10.102.1.23:8080"
        ]);
        $client->setLogger($this->logger);
        $res = $client->getTransaksiBakum($params['namabadanhukum']);

        return new SimpleResponse($res);
    }

    public function testTransaksiBakum() {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);
        $rawBody = $this->request->getJsonRawBody(true);
        $params = $this->validate(
            $rawBody,
            [
                'nama' => ['validators' => ['required']]
            ]
        );
        $client = new AhuClient($this->config["ahu_prop"]);
        $res = $client->testTransaksiBakum($params['nama']);

        return new SimpleResponse($res);
    }

    public function importIndikatorPancek()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);
        $document = $this->getAndValidateImportFile2('document', ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], $this->request->getUploadedFiles());
        $indikators = [];
        $komponenIndikators = [];
        if (!empty($document)) {
            $filename = $document->getTempName();
            $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
            $worksheet = $spreadsheet->getActiveSheet();

            $currentCode = '';
            foreach ($worksheet->getRowIterator() as $row) {
                $rowIndex = $row->getRowIndex();
                $textCell = $worksheet->getCellByColumnAndRow(2, $rowIndex, false);
                $typeCell = $worksheet->getCellByColumnAndRow(3, $rowIndex, false);
                $codeCell = $worksheet->getCellByColumnAndRow(4, $rowIndex, false);
                if ($textCell && $typeCell && $codeCell) {
                    $type = $typeCell->getFormattedValue();
                    $code = $codeCell->getFormattedValue();
                    $text = $textCell->getFormattedValue();
//                    $f = false;
//                    if ($code === 'D.4.a') {
//                        $f = true;
//                    }
                    if ($type === 'i') {
                        if ($currentCode != $code) {
                            $currentCode = $code;
                            array_push($indikators, ['code' => $code, 'label' => "<p>".$this->eliminateString($text)."</p>"]);
                        } else {
                            $indexFound = 0;
                            $joinLabel = "<li>".$this->eliminateString($text)."</li>";
                            foreach ($indikators as $index => $i) {
                                if ($i['code'] == $currentCode) {
                                    $joinLabel = $i['label'] . $joinLabel;
                                    $indexFound = $index;
                                }
                            }
                            $indikators[$indexFound]['label'] = $joinLabel;
                        }
                    } else if($type === 'ki') {
                        if ($currentCode != $code) {
                            $currentCode = $code;
                            array_push($komponenIndikators, ['code' => $code, 'label' => "<p>".$this->eliminateString($text)."</p>"]);
                        } else {
                            $indexFound = 0;
                            $joinLabel = "<p>".$this->eliminateString($text)."</p>";
                            foreach ($komponenIndikators as $index => $ki) {
                                if ($ki['code'] == $currentCode) {
                                    $joinLabel = $ki['label'] . $joinLabel;
                                    $indexFound = $index;
                                }
                            }
                            $komponenIndikators[$indexFound]['label'] = $joinLabel;
                        }
                    }
                }
            }
        }
        return new SimpleResponse([
            'totalIndikators' => count($indikators),
            'totalKomponenIndikators' => count($komponenIndikators),
            'indikators' => $indikators,
            'komponenIndikators' => $komponenIndikators
        ]);

        // BUMN/BUMD
//        $q = "";
//        foreach ($indikators as $indikator) {
//            $q .= "UPDATE jaga.pancek_indikator SET label = '" . $indikator['label'] . "' WHERE code = '" . $indikator['code'] . "';\n";
//        }
//        foreach ($komponenIndikators as $komponenIndikator) {
//            $q .= "UPDATE jaga.pancek_komponen_indikator SET label = '" . $komponenIndikator['label'] . "' WHERE code = '" . $komponenIndikator['code'] . "';\n";
//        }

        // SWASTA
        $q = "";
        $order = 1;
        foreach ($indikators as $indikator) {
            $code = $indikator['code'];
            $label = $indikator['label'];
            $kspId = "(SELECT id FROM jaga.pancek_konsep_sistem_pencegahan WHERE code LIKE '".substr($code, 0, 1)."' AND formulir_type = 2)";
            $q .= "INSERT INTO jaga.pancek_indikator (konsep_sistem_pencegahan_id, code, label, view_order, formulir_type) VALUES (".$kspId.", '".$code."', '".$label."', ".$order.", 2);\n";
            $order++;
        }
        $order = 1;
        foreach ($komponenIndikators as $komponenIndikator) {
            $code = $komponenIndikator['code'];
            $label = $komponenIndikator['label'];
            $parentCode = strlen($code) > 5 ? substr($code, 0, 5) : null;
            $indikatorId = "(SELECT id FROM jaga.pancek_indikator WHERE code LIKE '".substr($code, 0, 3)."' AND formulir_type = 2)";
            $q .= "INSERT INTO jaga.pancek_komponen_indikator (indikator_id, code, parent_code, label, is_header, view_order, bobot, formulir_type) VALUES (".$indikatorId.", '".$code."', ".($parentCode ? "'" . $parentCode . "'" : "null").", '".$label."', false, ".$order.", 0, 2);\n";
            $order++;
        }

        return new SimpleResponse($q);
    }

    public function readExcelBoptn()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);
        $document = $this->getAndValidateImportFile2('document', ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], $this->request->getUploadedFiles());
        $alokasi = $detailAlokasi = $notFoundPt = [];
        $infoAlokasis = InfoAlokasiBOPTN::find(['columns'=> 'id, kode_output','conditions' => 'tahun = 2022'])->toArray();
        $perguruanTinggis = PerguruanTinggi::find()->toArray();
        if (!empty($document)) {
            $filename = $document->getTempName();
            $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
            $worksheet = $spreadsheet->getActiveSheet();

            foreach ($worksheet->getRowIterator() as $row) {
                $rowIndex = $row->getRowIndex();
                $output = $worksheet->getCellByColumnAndRow(1, $rowIndex, false);
                $value = $worksheet->getCellByColumnAndRow(2, $rowIndex, false);
                if ($output && $value) {
                    $output = $output->getFormattedValue();
                    $value = $value->getValue();
                    if (!isset($pt)) {
                        $pt = null;
                    }
                    if (is_numeric($value)) {
                        $isHeader = true;
                        foreach ($infoAlokasis as $infoAlokasi) {
                            if (str_contains($output, $infoAlokasi['kode_output'])) {
                                $isHeader = false;
                                array_push($detailAlokasi[$pt], [
                                    'id_info_alokasi' => $infoAlokasi['id'],
                                    'output' => $output,
                                    'kode_info_alokasi' => $infoAlokasi['kode_output'],
                                    'value' => $value
                                ]);
                                break;
                            }
                        }
                        if ($isHeader) {
                            $pt = null;
                            $isPtFound = false;
                            foreach ($perguruanTinggis as $perguruanTinggi) {
                                if (str_contains(strtolower($output), strtolower($perguruanTinggi['nama']))) {
                                    $pt = $perguruanTinggi['nama'];
                                    array_push($alokasi, [
                                        'nama' => $pt,
                                        'output' => $output,
                                        'value' => $value
                                    ]);
                                    $isPtFound = true;
                                    break;
                                }
                            }
                            if (!$isPtFound) {
                                array_push($notFoundPt, ['output' => $output, 'value' => $value]);
                                $pt = $output;
                            }
                            $detailAlokasi[$pt] = [];
                        }
                    }
                }
            }

            // generate alokasi_boptn_bpptnbh
//            $spreadsheet = new Spreadsheet();
//            $sheet = $spreadsheet->getActiveSheet();
//            $sheet->setCellValue("A1", 'nama_perguruan_tinggi');
//            $sheet->setCellValue("B1", "tahun");
//            $sheet->setCellValue("C1", "nilai_alokasi");
//
//            $row = 1;
//            foreach ($alokasi as $data) {
//                $row++;
//                $sheet->setCellValue("A$row", $data['nama']);
//                $sheet->setCellValue("B$row", 2022);
//                $sheet->setCellValue("C$row", $data['value']);
//            }
//            $writer = new Xlsx($spreadsheet);
//            $filename = "generated_alokasi_boptn_bpptnbh_2022.xlsx";
//            header('Content-type: application/vnd.ms-excel');
//            header('Content-Disposition: attachment; filename="' . $filename . '"');
//            return $writer->save('php://output');

            // generate detail_alokasi_boptn
            $spreadsheet = new Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();
            $sheet->setCellValue("A1", 'nama_perguruan_tinggi');
            $sheet->setCellValue("B1", "tahun");
            $sheet->setCellValue("C1", "kode_alokasi");
            $sheet->setCellValue("D1", "nilai_alokasi");

            $row = 1;
            foreach ($detailAlokasi as $pt => $data) {
                foreach ($data as $datum) {
                    $row++;
                    $sheet->setCellValue("A$row", $pt);
                    $sheet->setCellValue("B$row", 2022);
                    $sheet->setCellValue("C$row", $datum['kode_info_alokasi']);
                    $sheet->setCellValue("D$row", $datum['value']);
                }
            }
            $writer = new Xlsx($spreadsheet);
            $filename = "generated_detail_alokasi_boptn_2022.xlsx";
            header('Content-type: application/vnd.ms-excel');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            return $writer->save('php://output');

        }
        return new CollectionPaginatedResponse($detailAlokasi);
    }

    public function readExcelBpptnbh()
    {
        $this->checkIsAuthenticated();
        AuthHelper::validateToolsKey($this->request, $this->config);
        $document = $this->getAndValidateImportFile2('document', ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], $this->request->getUploadedFiles());
        $alokasi = $notfound = [];
        $perguruanTinggis = PerguruanTinggi::find()->toArray();
        if (!empty($document)) {
            $filename = $document->getTempName();
            $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
            $worksheet = $spreadsheet->getActiveSheet();

            foreach ($worksheet->getRowIterator() as $row) {
                $rowIndex = $row->getRowIndex();
                $satker = $worksheet->getCellByColumnAndRow(1, $rowIndex, false);
                $nominal = $worksheet->getCellByColumnAndRow(2, $rowIndex, false);

                if ($satker && $nominal) {
                    $satker = $satker->getFormattedValue();
                    $nominal = $nominal->getValue();
                    if (is_numeric($nominal)) {
                        $found = false;
                        foreach ($perguruanTinggis as $perguruanTinggi) {
                            if (str_contains(strtolower($satker), strtolower($perguruanTinggi['nama']))) {
                                array_push($alokasi, [
                                    'pt' => $perguruanTinggi['nama'],
                                    'nominal' => $nominal
                                ]);
                                $found = true;
                                break;
                            }
                        }
                        if (!$found) {
                            array_push($notfound, [
                                'satker' => $satker,
                                'nominal' => $nominal
                            ]);
                        }
                    }
                }
            }

            // generate template detail_alokasi_bppthnbh
            $spreadsheet = new Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();
            $sheet->setCellValue("A1", 'nama_perguruan_tinggi');
            $sheet->setCellValue("B1", "tahun");
            $sheet->setCellValue("C1", "nilai_alokasi");

            $row = 1;
            foreach ($alokasi as $data) {
                $row++;
                $sheet->setCellValue("A$row", $data['pt']);
                $sheet->setCellValue("B$row", 2022);
                $sheet->setCellValue("C$row", $data['nominal']);
            }
            $writer = new Xlsx($spreadsheet);
            $filename = "generated_alokasi_bpptnbh_2022.xlsx";
            header('Content-type: application/vnd.ms-excel');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            return $writer->save('php://output');
        }
        return new CollectionPaginatedResponse($alokasi);
    }

    public function generateSitemap() {
        $this->checkScopes(['admin.view']);

        try {
            $beritas = Diskusi::find([
                "conditions" => "type = 1 AND is_deleted = 0",
                "order" => "updated_at desc"
            ]);

            $baseUrl = getenv("WEB_BASE_URL");
            $xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"UTF-8\" ?><urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\"></urlset>");

            foreach ($beritas as $berita) {
                $uuid = $berita->uuid;
                $title = preg_replace("/\s+/", "-", preg_replace("/[^a-zA-Z ]/", "", strtolower($berita->title)));
                try {
                    $lastmod = new DateTime($berita->updated_at);
                } catch (\Exception $e) {
                    $lastmod = new DateTime();
                }
                $url = $xml->addChild("url");
                $url->addChild("loc", "$baseUrl/berita/$uuid/$title");
                $url->addChild("lastmod", $lastmod->format("Y-m-d"));
            }

            $filename = "sitemap.xml";
            header('Content-type: text/xml');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            $path = $this->config['application']['publicDir'];
            $xml->saveXML("$path/files/$filename");
            $xml->saveXML('php://output');

            return null;
        } catch (\Exception $e) {
            throw new CustomErrorException(BaseResponse::UNEXPECTED_ERROR, $e->getMessage());
        }
    }

    public function apiTracker() {
        $this->checkScopes(['admin.view']);
        $params = $this->validate(
            $this->request->get(),
            [
                "name" => ["validators" => []]
            ]
        );
        $result = ApiTracker::find([
            "conditions" => "name ilike :name:",
            "bind" => ["name" => "%" . $params["name"] . "%"]
        ]);

        return new CollectionPaginatedResponse($result);
    }

    private function eliminateString($text)
    {
        $text = str_replace('a. ', '', $text);
        $text = str_replace('b. ', '', $text);
        $text = str_replace('c. ', '', $text);
        $text = str_replace('d. ', '', $text);
        $text = str_replace('e. ', '', $text);
        $text = str_replace('f. ', '', $text);
        $text = str_replace('g. ', '', $text);

        $text = str_replace('a. ', '', $text);
        $text = str_replace('b. ', '', $text);
        $text = str_replace('c. ', '', $text);
        $text = str_replace('d. ', '', $text);
        $text = str_replace('e. ', '', $text);
        $text = str_replace('f. ', '', $text);
        $text = str_replace('g. ', '', $text);

        $text = str_replace('    - ', '', $text);

        $text = str_replace('1. ', '', $text);

        $text = str_replace(' ', '', $text);

        $text = trim($text);
        return $text;
    }

    public function testKorsupgahFile($uuid) {
        $this->checkScopes(['admin.view']);
        $params = $this->validate(
            $this->request->get(),
            [
                'is_inline' => ['validators' => []],
                'id_survey' => ['validators' => ['required', 'digit']],
                'tahun' => ['validators' => ['required', 'digit']],
                'filename' => ['validators' => ['required']]
            ]
        );
        $isInline = $params['is_inline'] == null ? false : filter_var($params['is_inline'], FILTER_VALIDATE_BOOLEAN);
        $idSurvey = $params['id_survey'];
        $tahun = $params['tahun'];
        $filename = $params['filename'];

        if (getenv("FILESYSTEM_CLOUD") == FileSystemCloud::MINIO) {
            $result = [];
            /** @var MinioService $minioService */
            $minioService = $this->minio;
            $key = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR . $uuid;
            $isFileExist = $minioService->isFileExist(LogAttachments::KorsupgahAnswerAttachment, 'users_profpic' . DIRECTORY_SEPARATOR . $key);
            if ($isFileExist) {
                $url = $minioService->base_get_public_url('users_profpic' . DIRECTORY_SEPARATOR . $key, $filename, !$isInline);
                $result["minio-public"] = $url;
            } else {
                $subFolder = KorsupgahAnswerAttachment::getSubfolder($tahun, $idSurvey);
                $key = $subFolder . DIRECTORY_SEPARATOR . $uuid;
                if ($minioService->isSecondaryS3Available()) {
                    $url = $minioService->basePrivateUrlUsingSecondaryS3($key, $filename, !$isInline);
                    $result["aws-private"] = $url;
                } else {
                    $url = $minioService->base_get_private_url($key, $filename, !$isInline);
                    $result["minio-private"] = $url;
                }
            }
            return $result;
        } elseif (getenv("FILESYSTEM_CLOUD") == FileSystemCloud::LOCAL) {
            $subFolder = getenv("USER_IMAGE_FOLDER");
            $filename = $subFolder . DIRECTORY_SEPARATOR . $uuid;
            if (file_exists($filename)) {
                return MediaHelper::fileResponse($filename, null, true, $params['is_inline']);
            } else {
                $subFolder = getenv("PRIVATE_FOLDER") . KorsupgahAnswerAttachment::getSubfolder($tahun, $idSurvey);
                $filename = $subFolder . DIRECTORY_SEPARATOR . $uuid;
                if (file_exists($filename)) {
                    return MediaHelper::fileResponse($filename, null, true, $isInline);
                } else {
                    throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "File Not Found");
                }
            }
        }
    }

    public function generateRenamedAdmMapGeojson($admType) {
        $this->checkScopes(['admin.view']);
        AuthHelper::validateToolsKey($this->request, $this->config);
        $map = $this->request->getJsonRawBody(true);
        if (!array_key_exists('features', $map) || !is_array($map['features'])) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Map geojson tidak valid!");
        }

        if ($admType == 'provinsi') {
            $provinces = $this->rawQuery("SELECT 'ID' || provinsi_code as code, provinsi_name as name from master_provinsi;");
            $provincesKv = array_combine(array_column($provinces, 'code'), array_column($provinces, 'name'));
            foreach ($map['features'] as $index => $feature) {
                $code = $feature['properties']["ADM1_PCODE"];
                if (array_key_exists($code, $provincesKv)) {
                    $map['features'][$index]['properties']["ADM1_EN"] = 'PROVINSI ' . strtoupper($provincesKv[$code]);
                }
            }
        } elseif ($admType == 'kabkota') {
            $provinces = $this->rawQuery("SELECT 'ID' || provinsi_code as code, provinsi_name as name from master_provinsi;");
            $provincesKv = array_combine(array_column($provinces, 'code'), array_column($provinces, 'name'));
            $cities = $this->rawQuery("SELECT 'ID' || kota_kabupaten_code as code, kota_kabupaten_name as name FROM master_kota_kabupaten;");
            $citiesKv = array_combine(array_column($cities, 'code'), array_column($cities, 'name'));
            foreach ($map['features'] as $index => $feature) {
                $code = $feature['properties']["ADM1_PCODE"];
                if (array_key_exists($code, $provincesKv)) {
                    $map['features'][$index]['properties']["ADM1_EN"] = 'PROVINSI ' . strtoupper($provincesKv[$code]);
                }

                $code = $feature['properties']["ADM2_PCODE"];
                if (array_key_exists($code, $citiesKv)) {
                    $map['features'][$index]['properties']["ADM2_EN"] = strtoupper($citiesKv[$code]);
                }
            }
        } else {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Adm Level tidak valid!");
        }

        return $map;
    }

    public function getEnv($env) {
        $this->checkScopes(['admin.view']);

        $res = [
            $env => getenv($env)
        ];

        return new SimpleResponse($res);
    }
}

