<?php

namespace DetailTask;

use Bpjs2Client;
use BpjsKotaKabupaten;
use BpjsPuskesmas;
use BpjsPuskesmasKapitasi;
use LogHelper;
use ValidationException;

/**
 * @property Bpjs2Client $client
 */
class BpjsPuskesmasTask extends AbstractTask {
    #region Attributes
    private $listOfPuskesmas;
    private $puskesmasCounter;
    #endregion

    #region Main
    public function init() {
        $this->client = new Bpjs2Client($this->config['bpjs2_config']);
        $this->client->setLogger($this->logger);
        $this->puskesmasCounter = 0;
    }
    public function processBpjsPuskesmas() {
        $this->init();
        $startTime = microtime(true);
        $this->processName = "Process BPJS Puskesmas";
        try {
            $listKabupaten = $this->client->updateAndGetProvinsiKabKota();
            $updatedKabKota = [];
            if (is_countable($listKabupaten)) {
                if(count($listKabupaten) < 1) print_r("DATA IS UP TO DATE!");

                foreach ($listKabupaten as $kabupaten) {
                    $lastPage = ($kabupaten->puskesmas_last_update_page == null || $kabupaten->puskesmas_last_update_page == 'LAST') ? 1 : $kabupaten->puskesmas_last_update_page;

                    $respProfilPuskesmas = $this->client->getProfilPuskesmas($lastPage, $kabupaten->kodedati2);
                    if ($this->client->isBpjsResponseTimeout($respProfilPuskesmas)) {
                        print_r('GET DATA TIMEOUT AT kodedati2 = ' . $kabupaten->kodedati2 . ' PAGE = ' . $lastPage);
                        break;
                    }

                    if (array_key_exists('metaData', $respProfilPuskesmas)) {
                        if ($respProfilPuskesmas['metaData']['code'] == '200') {
                            $totalRecords = $respProfilPuskesmas['response']['count'];
                            $totalPage = ceil($totalRecords / 10);
                            $this->saveBpjsPuskesmasProfile($respProfilPuskesmas['response']['list'], $kabupaten->BpjsProvinsi, $kabupaten);
                            $lastPage++;

                            for ($page = $lastPage; $page <= $totalPage; $page++) {
                                $lastPage = $page;
                                $respProfilPuskesmas = $this->client->getProfilPuskesmas($page, $kabupaten->kodedati2);
                                if ($this->client->isBpjsResponseTimeout($respProfilPuskesmas)) {
                                    print_r('GET DATA TIMEOUT AT kodedati2 = ' . $kabupaten->kodedati2 . ' PAGE = ' . $lastPage);
                                    break;
                                }

                                if (array_key_exists('metaData', $respProfilPuskesmas)) {
                                    if ($respProfilPuskesmas['metaData']['code'] == '200') {
                                        $this->saveBpjsPuskesmasProfile($respProfilPuskesmas['response']['list'], $kabupaten->BpjsProvinsi, $kabupaten);
                                    }
                                }
                            }

                            if($lastPage >= $totalPage) $lastPage = 'LAST';

                        }
                    }
                    $updatedKabKota[] = [
                        'kodedati2' => $kabupaten->kodedati2,
                        'puskesmas_last_update_at' => date('Y-m-d H:i:s'),
                        'puskesmas_last_update_page' => $lastPage
                    ];
                }

                $this->handleUpdateBpjsKabKota($updatedKabKota);
            }

            LogHelper::logInfo($this->processName ." ended", $startTime, microtime(true), [$this->puskesmasCounter . " puskesmas successfully updated"], self::LOG_TYPE, $this->logger);
        } catch (\Exception $e) {
            LogHelper::logInfo($this->processName ." ended with exception", $startTime, microtime(true), [$e->getMessage(), $this->puskesmasCounter . " puskesmas successfully updated"], self::LOG_TYPE, $this->logger);
            print_r($e->getMessage());
        }
    }

    /**
     * @return void
     * Logging disimpan ke file log
     */
    public function processBpjsPuskesmasKapitasi() {
        $this->init();
        $startTime = microtime(true);
        $this->processName = "Process BPJS Puskesmas Kapitasi";
        try {
            $this->setListOfPuskesmas();
            foreach ($this->listOfPuskesmas as $puskesmas) {
                /** @var BpjsPuskesmas $puskesmas */
                $kodepuskesmas = $puskesmas->kodepuskesmas;
                $resKapitasi = $this->client->getKapitasi($kodepuskesmas);
                if ($this->client->isBpjsResponseTimeout($resKapitasi)) {
                    print_r('GET DATA KAPITASI TIMEOUT AT id = ' . $puskesmas->id . ' kodepuskesmas = ' . $kodepuskesmas);
                    LogHelper::logInfo($this->processName . " ended with timeout", $startTime, microtime(true), ["kodepuskesmas = " . $kodepuskesmas, $this->puskesmasCounter . " puskesmas successfully updated"], self::LOG_TYPE, $this->logger);
                    break;
                } else {
                    if ($this->client->isBpjsResponseSuccess($resKapitasi)) {
                        $list = $resKapitasi['response']['list'];
                        $this->handleSaveKapitasi($list, $puskesmas, $kodepuskesmas);
                    }
                    else {
                        print_r('GET DATA KAPITASI NOT SUCCESS AT id = ' . $puskesmas->id . ' kodepuskesmas = ' . $kodepuskesmas);
                        LogHelper::logInfo($this->processName . " ended with failed response from BPJS", $startTime, microtime(true), ["kodepuskesmas = " . $kodepuskesmas, $this->puskesmasCounter . " puskesmas successfully updated"], self::LOG_TYPE, $this->logger);
                        break;
                    }
                }
            }

            LogHelper::logInfo($this->processName . " ended", $startTime, microtime(true), [$this->puskesmasCounter . " puskesmas successfully updated"], self::LOG_TYPE, $this->logger);
        }
        catch (\Exception $e) {
            LogHelper::logInfo($this->processName . " ended with exception", $startTime, microtime(true), [$e->getMessage(), $this->puskesmasCounter . " puskesmas successfully updated"], self::LOG_TYPE, $this->logger);
            print_r($e->getMessage());
        }
    }
    #endregion

    #region Helper
    private function setListOfPuskesmas() {
        $this->listOfPuskesmas = BpjsPuskesmas::find([
            'conditions' => 'last_update_kapitasi IS NULL OR last_update_kapitasi <= ?0',
            'bind' => [
                date('Y-m-d', strtotime('-' . Bpjs2Client::FILTER_LAST_UPDATE . ' day'))
            ],
            "order" => "id",
            "limit" => "1000",
            "offset" => "0"
        ]);
    }

    private function saveBpjsPuskesmasProfile($listPuskesmas, $dataProvinsi, $dataKabupaten)
    {
        try {
            foreach ($listPuskesmas as $dataPuskesmas) {
                $bpjsPuskesmas = BpjsPuskesmas::findFirst([
                    'conditions' => 'kodepuskesmas = :kodepuskesmas:',
                    'bind' => [
                        'kodepuskesmas' => $dataPuskesmas['kodepuskesmas']
                    ]
                ]);
                if (empty($bpjsPuskesmas)) {
                    $bpjsPuskesmas = new BpjsPuskesmas();
                }
                $bpjsPuskesmas->kodepuskesmas = $dataPuskesmas['kodepuskesmas'];
                $bpjsPuskesmas->namapuskesmas = $dataPuskesmas['namapuskesmas'];
                $bpjsPuskesmas->kodepropinsi = $dataProvinsi->kodepropinsi;
                $bpjsPuskesmas->kodepropinsikemendagri = $dataProvinsi->kodepropinsikemendagri;
                $bpjsPuskesmas->namapropinsi = $dataProvinsi->namapropinsi;
                $bpjsPuskesmas->kodedati2 = $dataKabupaten->kodedati2;
                $bpjsPuskesmas->kodedati2kemendagri = $dataKabupaten->kodedati2kemendagri;
                $bpjsPuskesmas->namadati2 = $dataKabupaten->namadati2;
                $bpjsPuskesmas->namakec = $dataPuskesmas['namakec'];
                $bpjsPuskesmas->namadesa = $dataPuskesmas['namadesa'];
                $bpjsPuskesmas->alamat = $dataPuskesmas['alamat'];
                $bpjsPuskesmas->namakepala = $dataPuskesmas['namakepala'];
                $bpjsPuskesmas->namapenanggungjawab = $dataPuskesmas['namapenanggungjawab'];
                $bpjsPuskesmas->jumlahdokter = $dataPuskesmas['jumlahdokter'];
                $bpjsPuskesmas->jumlahdoktergigi = $dataPuskesmas['jumlahdoktergigi'];
                $bpjsPuskesmas->jumlahperawat = $dataPuskesmas['jumlahperawat'];
                $bpjsPuskesmas->jumlahapoteker = $dataPuskesmas['jumlahapoteker'];
                $bpjsPuskesmas->jumlahasistenapoteker = $dataPuskesmas['jumlahasistenapoteker'];
                $bpjsPuskesmas->jumlahbidan = $dataPuskesmas['jumlahbidan'];
                $bpjsPuskesmas->jumlahahligizi = $dataPuskesmas['jumlahahligizi'];
                $bpjsPuskesmas->listdokter = json_encode($dataPuskesmas['listdokter']);
                $bpjsPuskesmas->listdoktergigi = json_encode($dataPuskesmas['listdoktergigi']);
                $bpjsPuskesmas->tglpengajuanpaktaintegritas = $dataPuskesmas['tglpengajuanpaktaintegritas'];
                $status = $bpjsPuskesmas->save();
                if (!$status) {
                    $errors = $bpjsPuskesmas->getMessages();
                    $error_messages = [];

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

                    throw new ValidationException($error_messages);
                }
                $this->puskesmasCounter++;
            }
        }
        catch (\Exception $exception) {
            \Sentry\captureException($exception);
            print_r($exception->getMessage());
        }
    }

    private function handleSaveKapitasi($listOfKapitasi, BpjsPuskesmas $puskesmas, $kodePuskesmas) {
        // data kapitasi tidak ditemukan
        if (sizeof($listOfKapitasi) == 0) {
            $puskesmas->last_update_kapitasi = 'now()';
            $puskesmas->save();
        } else {
            $success = 0;
            foreach ($listOfKapitasi as $item) {
                $kapitasi = BpjsPuskesmasKapitasi::findFirst([
                    'conditions' => 'kodepuskesmas = ?0 AND bulan = ?1',
                    'bind' => [
                        $kodePuskesmas,
                        $item['bulan']
                    ]
                ]);
                if (empty($kapitasi)) {
                    $kapitasi = new BpjsPuskesmasKapitasi();
                }
                $kapitasi->kodepuskesmas = $kodePuskesmas;
                $kapitasi->namapuskesmas = $item['namapuskesmas'];
                $kapitasi->bulan = $item['bulan'];
                $kapitasi->jumlahpeserta = $item['jumlahpeserta'];
                $kapitasi->danakapitasi = $item['danakapitasi'];
                $kapitasi->tanggalproses = $item['tanggalproses'];
                if ($kapitasi->save()) $success++;
            }

            if ($success > 0) {
                $puskesmas->last_update_kapitasi = 'now()';
                $puskesmas->save();
            }
        }
        $this->puskesmasCounter++;
    }

    private function handleUpdateBpjsKabKota($listOfKabKota) {
        foreach ($listOfKabKota as $update) {
            $kabupatens = BpjsKotaKabupaten::find([
                'conditions' => 'kodedati2 = ?0',
                'bind' => [
                    $update['kodedati2']
                ]
            ]);
            foreach ($kabupatens as $item) {
                $item->puskesmas_last_update_at = $update['puskesmas_last_update_at'];
                $item->puskesmas_last_update_page = $update['puskesmas_last_update_page'];
                $item->save();
            }
        }
    }
    #endregion
}
