<?php

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class KorwilPadTargetController extends BaseController
{
    /** @var UmUser $currentUser */
    protected $currentUser;
    /** @var KorwilPadTarget $kpt */
    protected $kpt;

    public function setCurrentUser(UmUser $user) {
        $this->currentUser = $user;
    }

    public function setKpt(KorwilPadTarget  $kpt) {
        $this->kpt = $kpt;
    }

    public function list()
    {
        $this->checkIsAuthenticated();

        $getParams = $this->request->get();

        $getParams['id_instansi'] = array_key_exists('id_instansi', $getParams) ? $getParams['id_instansi'] : null;
        $getParams['limit'] = $this->getDefaultLimit($getParams);
        $getParams['offset'] = array_key_exists('offset', $getParams) ? $getParams['offset'] : 0;
        $getParams['keyword'] = array_key_exists('keyword', $getParams) ? $getParams['keyword'] : '';

        $params =  $this->validate(
            $getParams,
            [
                'limit' => ['validators' => ['digit']],
                'offset' => ['validators' => ['digit']],
                'keyword' => ['validators' => []],
                'id_instansi' => ['validators' => ['digit']]
            ]
        );

        $builder = $this->modelsManager->createBuilder()->from('KorwilPadTarget')
            ->join('Instansi', 'KorwilPadTarget.id_instansi = Instansi.id')
            ->orderBy('KorwilPadTarget.id')
            ->limit($params['limit'])
            ->offset($params['offset']);

        $countBuilder = $this->modelsManager->createBuilder()->from('KorwilPadTarget')
            ->columns(['total_record' => 'COUNT(*)'])
            ->join('Instansi', 'KorwilPadTarget.id_instansi = Instansi.id')
            ->limit(1);

        if (!empty($params['id_instansi'])) {
            $builder->where('Instansi.id = :id_instansi:', ['id_instansi' => $params['id_instansi']]);
            $countBuilder->where('Instansi.id = :id_instansi:', ['id_instansi' => $params['id_instansi']]);
        }

        if (!empty($params['keyword'])) {
            $builder->where('Instansi.nama ilike :keyword:', ['keyword' => '%' . $params['keyword'] . '%'])
                ->orWhere('KorwilPadTarget.tahun ilike :keyword:', ['keyword' => '%' . $params['keyword'] . '%']);

            $countBuilder->where('Instansi.nama ilike :keyword:', ['keyword' => '%' . $params['keyword'] . '%'])
                ->orWhere('KorwilPadTarget.tahun ilike :keyword:', ['keyword' => '%' . $params['keyword'] . '%']);
        }

        $rows = $builder->getQuery()->execute();

        $kpt = [];
        foreach ($rows as $key => $survey) {
            $kpt[] = $survey->toDetail();
        }

        $total_record = (int) $countBuilder->getQuery()->execute()->getFirst()->total_record;

        return new PaginatedResponse($kpt, $total_record, $params['limit'], $params['offset']);
    }

    public function listWithDetail()
    {
        $this->checkOneOfScopes(['korsupgah.monitoring', 'korwil.monitoring_kemdagri', 'korwil.monitoring_bpkp', 'korwil.verifikator_kemdagri_bpkp', 'korwil.observer_kemdagri_bpkp']);

        $getParams = $this->request->get();

        $getParams['limit'] = $this->getDefaultLimit($getParams);
        $getParams['offset'] = array_key_exists('offset', $getParams) ? $getParams['offset'] : 0;
        $getParams['id_instansi'] = array_key_exists('id_instansi', $getParams) ? $getParams['id_instansi'] : -1;

        $params =  $this->validate(
            $getParams,
            [
                'limit' => ['validators' => ['digit']],
                'offset' => ['validators' => ['digit']],
                'id_instansi' => ['validators' => ['digit']]
            ]
        );

        $instansi_operator = $params < 0 ? '<>' : '=';

        $kpt = KorwilPadTarget::find([
            'conditions' => "id_instansi $instansi_operator :id_instansi:",
            'bind' => [
                'id_instansi' => $params['id_instansi']
            ],
            'limit' => $params['limit'],
            'offset' => $params['offset']
        ]);

        $total_record = KorwilPadTarget::count([
            'conditions' => "id_instansi $instansi_operator :id_instansi:",
            'bind' => [
                'id_instansi' => $params['id_instansi']
            ]
        ]);

        $result = [];

        foreach ($kpt as $key => $target) {
            $result[] = $target->toDetail();
        }

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

    public function detail($id)
    {
        $this->checkIsAuthenticated();

        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD tidak ditemukan');
        }

        $result = $kpt->toDetail();

        return new CollectionPaginatedResponse([$result]);
    }

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

        $rawBody = $this->request->getJsonRawBody(true);

        $params = $this->validate(
            $rawBody,
            [
                'id_instansi' => ['validators' => ['required', 'digit']],
                'tahun' => ['validators' => []],
                'nilai' => ['validators' => []]
            ]
        );

        $instansi = Instansi::findFirst($params['id_instansi']);
        if (empty($instansi)) :
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi tidak ditemukan');
        endif;

        if (!empty($instansi->deleted_at)) :
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah terhapus');
        endif;

        $cekPadTarget = KorwilPadTarget::findFirst([
            'conditions' => 'id_instansi = :id: AND tahun = :tahun:',
            'bind' => [
                'id' => $params['id_instansi'],
                'tahun' => $params['tahun']
            ]
        ]);

        if (!empty($cekPadTarget)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah memiliki target PAD di tahun yang sama');
        }

        $kpt = new KorwilPadTarget();
        $kpt->id_instansi = $params['id_instansi'];
        $kpt->tahun = $params['tahun'];
        $kpt->nilai = $params['nilai'];
        $kpt->created_at = date('Y-m-d H:i:s');
        $kpt->created_by = $this->shared->user->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessages();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = ["field" => $error->getField(), "message" => $error->getMessage()];
            }

            throw new ValidationException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

    public function createMine()
    {
        $this->checkOneOfScopes(['korsupgah.answer', 'pad.answer']);

        $rawBody = $this->request->getJsonRawBody(true);

        $params = $this->validate(
            $rawBody,
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'nilai' => ['validators' => ['required', 'digit']]
            ]
        );

        $this->setAndValidateUser();
        $idInstansi = $this->currentUser->id_instansi;

        $cekPadTarget = KorwilPadTarget::findFirst([
            'conditions' => 'id_instansi = :id: AND tahun = :tahun:',
            'bind' => [
                'id' => $idInstansi,
                'tahun' => $params['tahun']
            ]
        ]);

        if (!empty($cekPadTarget)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah memiliki target PAD di tahun yang sama');
        }

        $kpt = new KorwilPadTarget();
        $kpt->id_instansi = $idInstansi;
        $kpt->tahun = $params['tahun'];
        $kpt->nilai = $params['nilai'];
        $kpt->created_at = date('Y-m-d H:i:s');
        $kpt->created_by = $this->currentUser->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessages();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = ["field" => $error->getField(), "message" => $error->getMessage()];
            }

            throw new ValidationException($error_messages);
        }

        return new CollectionPaginatedResponse([$kpt]);
    }

    public function update($id)
    {
        $this->checkScopes(['korsupgah.admin']);

        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Tidak Ditemukan');
        }

        if (!empty($kpt->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Sudah Terhapus');
        }

        $rawBody = $this->request->getJsonRawBody(true);

        $params = $this->validate(
            $rawBody,
            [
                'id_instansi' => ['validators' => ['required', 'digit']],
                'tahun' => ['validators' => []],
                'nilai' => ['validators' => []]
            ]
        );

        $instansi = Instansi::findFirst($params['id_instansi']);
        if (empty($instansi)) :
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi tidak ditemukan');
        endif;

        if (!empty($instansi->deleted_at)) :
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah terhapus');
        endif;

        $cekPadTarget = KorwilPadTarget::findFirst([
            'conditions' => 'id_instansi = :id: AND tahun = :tahun:',
            'bind' => [
                'id' => $params['id_instansi'],
                'tahun' => $params['tahun']
            ]
        ]);

        if (!empty($cekPadTarget) && $kpt->id != $cekPadTarget->id) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah memiliki target PAD di tahun yang sama');
        }

        $date = date('Y-m-d H:i:s');
        $kpt->id_instansi = $params['id_instansi'];
        $kpt->tahun = $params['tahun'];
        $kpt->nilai = $params['nilai'];
        $kpt->updated_at = $date;
        $kpt->updated_by = $this->shared->user->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessage();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = [
                    "field" => $error->getField(), "message" => $error->getMessage()
                ];
            }

            throw new ValidationsException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

    public function updateMine($id)
    {
        $this->checkOneOfScopes(['korsupgah.answer', 'pad.answer']);

        $rawBody = $this->request->getJsonRawBody(true);

        $params = $this->validate(
            $rawBody,
            [
                'tahun' => ['validators' => ['required', 'digit']],
                'nilai' => ['validators' => ['required', 'digit']]
            ]
        );

        /** @var KorwilPadTarget $kpt */
        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Tidak Ditemukan');
        }

        if (!empty($kpt->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Sudah Terhapus');
        }

        $this->setAndValidateUserKpt($kpt);
        $idInstansi = $this->currentUser->id_instansi;

        /** @var KorwilPadTarget $cekPadTarget */
        $cekPadTarget = KorwilPadTarget::findFirst([
            'conditions' => 'id_instansi = :id: AND tahun = :tahun:',
            'bind' => [
                'id' => $idInstansi,
                'tahun' => $params['tahun']
            ]
        ]);

        if (!empty($cekPadTarget) && $kpt->id != $cekPadTarget->id) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah memiliki Target PAD di tahun yang sama');
        }

        $date = date('Y-m-d H:i:s');
        $kpt->id_instansi = $idInstansi;
        $kpt->tahun = $params['tahun'];
        $kpt->nilai = $params['nilai'];
        $kpt->updated_at = $date;
        $kpt->updated_by = $this->currentUser->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessage();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = [
                    "field" => $error->getField(), "message" => $error->getMessage()
                ];
            }

            throw new ValidationException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

    public function delete($id)
    {
        $this->checkScopes(['korsupgah.admin']);

        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Tidak Ditemukan');
        }

        if (!empty($kpt->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Sudah Terhapus');
        }

        $now = date('Y-m-d H:i:s');
        $kpt->updated_at = $now;
        $kpt->deleted_at = $now;
        $kpt->updated_by = $this->shared->user->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessages();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = ["field" => $error->getField(), "message" => $error->getMessages()];
            }

            throw new ValidationException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

    public function deleteMine($id)
    {
        $this->checkOneOfScopes(['korsupgah.answer', 'pad.answer']);

        /** @var KorwilPadTarget $kpt */
        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Tidak Ditemukan');
        }

        if (!empty($kpt->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Sudah Terhapus');
        }

        $this->setAndValidateUserKpt($kpt);
        $idInstansi = $this->currentUser->id_instansi;

        if ($kpt->id_instansi != $idInstansi) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'User tidak berhak mengakses');
        }

        $now = date('Y-m-d H:i:s');
        $kpt->updated_at = $now;
        $kpt->deleted_at = $now;
        $kpt->updated_by = $this->currentUser->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessages();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = ["field" => $error->getField(), "message" => $error->getMessages()];
            }

            throw new ValidationException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

    public function restore($id)
    {
        $this->checkScopes(['korsupgah.admin']);

        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Tidak Ditemukan');
        }

        if (empty($kpt->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD sudah aktif');
        }


        $now = date('Y-m-d H:i:s');
        $kpt->updated_at = $now;
        $kpt->deleted_at = null;
        $kpt->updated_by = $this->shared->user->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessages();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = ["field" => $error->getField(), "message" => $error->getMessage()];
            }

            throw new ValidationException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

    public function restoreMine($id)
    {
        $this->checkOneOfScopes(['korsupgah.answer', 'pad.answer']);

        $kpt = KorwilPadTarget::findFirst($id);

        if (empty($kpt)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD Tidak Ditemukan');
        }

        if (empty($kpt->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target PAD sudah aktif');
        }

        $this->setAndValidateUserKpt($kpt);

        $now = date('Y-m-d H:i:s');
        $kpt->updated_at = $now;
        $kpt->deleted_at = null;
        $kpt->updated_by = $this->currentUser->um_id;
        $status = $kpt->save();

        if (!$status) {
            $errors = $kpt->getMessages();
            $error_messages = [];

            foreach ($errors as $key => $error) {
                $error_messages[] = ["field" => $error->getField(), "message" => $error->getMessage()];
            }

            throw new ValidationException($error_messages);
        } else {
            return new CollectionPaginatedResponse([$kpt]);
        }
    }

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

        // $result = KorwilPadTarget::find();
        $query = "SELECT korwil_pad_target.*, instansi.nama FROM korwil_pad_target left join instansi on instansi.id = korwil_pad_target.id_instansi";

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

        $header = [
            "id_instansi",
            "nama_instansi",
            "tahun",
            "nilai"
        ];

        $rows = [];
        $rows[] = $header;
        foreach ($result as $index => $data) {
            $rows[] = [
                $data['id_instansi'],
                $data['nama'],
                $data['tahun'],
                $data['nilai']
            ];
        }

        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->fromArray($rows, NULL, 'A1');


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

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

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

        $failed = [];
        $updated = [];
        $added = [];

        if (!empty($document)) {
            $filename = $document['tmp_name'];
            $rows = [];
            if ($_FILES['document']['type'] == 'text/csv') {
                $csv = new ParseCsv\Csv();
                $csv->parse($filename);
                $rows = $csv->data;
            } else {
                try{
                    $spreadsheet = PhpOffice\PhpSpreadsheet\IOFactory::load($filename);
                    $worksheet = $spreadsheet->getActiveSheet()->toArray();
                    for ($i = 1; $i < sizeof($worksheet); $i++) {
                        $tmp = [];
                        foreach ($worksheet[0] as $key => $value) {
                            $tmp[$value] = $worksheet[$i][$key];
                        }
                        array_push($rows, $tmp);
                    }
                } catch (\Exception $e) {
                    throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Format file excel tidak valid! Detail: " . $e->getMessage());
                }
            }

            foreach ($rows as $key => $row) {
                if (!empty($row['id_instansi']) && !empty($row['tahun']) && !empty($row['nilai'])) {
                    if (empty($row['id_instansi']) || empty($row['tahun']) || empty($row['nilai'])) {
                        throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Id Instansi/tahun/nilai tidak ditemukan pada baris ' . ($key + 2));
                    }

                    $instansi = Instansi::findFirst($row['id_instansi']);

                    if (empty($instansi)) {
                        throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi tidak ditemukan: ' . $row['id_instansi']);
                    }

                    if (!empty($instansi->deleted_at)) {
                        throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi: ' . $row['id_instansi'] . ' sudah terhapus');
                    }

                    $cekPadTarget = KorwilPadTarget::findFirst([
                        'conditions' => 'id_instansi=:id_instansi: AND tahun=:tahun: AND deleted_at is NULL',
                        'bind' => [
                            'id_instansi' => $row['id_instansi'],
                            'tahun' => $row['tahun']
                        ]
                    ]);

                    if (!empty($cekPadTarget)) {
                        $cekPadTarget->id_instansi = $row['id_instansi'];
                        $cekPadTarget->tahun = $row['tahun'];
                        $cekPadTarget->nilai = $row['nilai'];
                        $status = $cekPadTarget->save();

                        if ($status) {
                            $updated[] = ['id_instansi' => $row['id_instansi'], 'tahun' => $row['tahun'], 'nilai' => $row['nilai']];
                        } else {
                            $failed[] = ['id_instansi' => $row['id_instansi'], 'tahun' => $row['tahun'], 'nilai' => $row['nilai']];
                        }
                    } else {
                        $setNewPadTarget = new KorwilPadTarget();
                        $setNewPadTarget->id_instansi = $row['id_instansi'];
                        $setNewPadTarget->tahun = $row['tahun'];
                        $setNewPadTarget->nilai = $row['nilai'];
                        $status = $setNewPadTarget->save();

                        if ($status) {
                            $added[] = ['id_instansi' => $row['id_instansi'], 'tahun' => $row['tahun'], 'nilai' => $row['nilai']];
                        } else {
                            $failed[] = ['id_instansi' => $row['id_instansi'], 'tahun' => $row['tahun'], 'nilai' => $row['nilai']];
                        }
                    }
                }
            }
        }

        return new SimpleResponse(compact(['added', 'failed', 'updated']));
    }

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

        $params = $this->request->get();
        $idInstansi = array_key_exists('id_instansi', $params) ? $params['id_instansi'] : null;

        $qInstansi = "";
        if($idInstansi) {
            Instansi::findOrFail($idInstansi);
            $qInstansi .= " AND id = " . $idInstansi;
        }

        $result = [];
        $data = Instansi::find([
            'columns' => 'id, nama, id_provinsi',
            'conditions' => 'id_tipe = 1 AND deleted_at is NULL' . $qInstansi,
            'order' => 'id_provinsi'
        ]);
        foreach ($data as $provinsi) {
            array_push($result, ['id' => $provinsi->id, 'nama' => $provinsi->nama, 'is_provinsi' => true]);
            $params = [
                'columns' => 'id, nama',
                'conditions' => 'id_tipe = 2 AND id_provinsi = :id_provinsi: AND deleted_at is NULL',
                'order' => 'id_kota_kabupaten',
                'bind' => ['id_provinsi' => $provinsi->id_provinsi]
            ];
            $kabKotas = Instansi::find($params);
            foreach ($kabKotas as $kabKota) {
                array_push($result, ['id' => $kabKota->id, 'nama' => $kabKota->nama, 'is_provinsi' => false]);
            }
        }

        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setCellValue("A1", 'id_instansi');
        $sheet->setCellValue("B1", 'nama_instansi');
        $sheet->setCellValue("C1", 'tahun');
        $sheet->setCellValue("D1", 'nilai');

        $rowIdx = 2;
        foreach ($result as $item) {
            $sheet->setCellValue("A$rowIdx", $item['id']);
            $sheet->setCellValue("B$rowIdx", $item['nama']);
            if ($item['is_provinsi']) {
                $sheet->getStyle("A$rowIdx:B$rowIdx")
                    ->getFont()->setBold(true);
            }
            $rowIdx++;
        }
        $sheet->getColumnDimension('A')->setAutoSize(true);
        $sheet->getColumnDimension('B')->setAutoSize(true);
        $sheet->getColumnDimension('C')->setAutoSize(true);
        $sheet->getColumnDimension('D')->setAutoSize(true);

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

    public function canVerify()
    {
        $getParams = $this->request->get();

        $params = $this->validate(
            $getParams,
            [
                'id' => ['validators' => ['required', 'digit']]
            ]
        );

        $target = KorwilPadTarget::findFirst($params['id']);

        if (empty($target)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Target tidak ditemukan');
        }

        $teamCount = $this->countRelatedTeam($this->shared->user->um_id, $target->id_instansi);

        return new SimpleResponse(['total' => $teamCount]);
    }

    /**
     * @throws CustomErrorException
     */
    private function setAndValidateUser() {
        $currentUser = $this->shared->user;
        if (!$currentUser) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'User tidak berhak mengakses.');
        }

        $idInstansi = $currentUser->id_instansi;
        if (!$idInstansi) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'User tidak memiliki instansi');
        }

        $instansi = Instansi::findFirst($idInstansi);
        if (empty($instansi)) :
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi tidak ditemukan');
        endif;

        if (!empty($instansi->deleted_at)) :
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, 'Instansi sudah terhapus');
        endif;

        $this->setCurrentUser($currentUser);
    }

    private function validateUserInstansiAndKptInstansi() {
        if (!$this->currentUser || !$this->kpt || $this->currentUser->id_instansi != $this->kpt->id_instansi) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "User tidak berhak mengakses");
        }
    }

    private function setAndValidateUserKpt(KorwilPadTarget $kpt) {
        $this->setKpt($kpt);
        $this->setAndValidateUser();
        $this->validateUserInstansiAndKptInstansi();
    }
}
