<?php

/**
 * Class OmspanMasterDesa
 * @method static OmspanMasterDesa|boolean findFirstByKodeDesa(string $kodeDesa)
 * @property KemdagriKepadatanPendudukPerDesa $kkppd
 */
class OmspanMasterDesa extends \Phalcon\Mvc\Model
{
    public $id;
    public $kode_pemda;
    public $kode_lokasi;
    public $kode_area;
    public $nama_area;
    public $kode_provinsi;
    public $nama_provinsi;
    public $nama_pemda;
    public $kode_kecamatan;
    public $nama_kecamatan;
    public $kode_desa;
    public $nama_desa;

    private $updatedAt;

    public function initialize()
    {
        $this->setSchema("jaga");
        $this->setSource("omspan_master_desa");
        $this->hasOne('kode_desa', '\DesaJumlahPenduduk', 'kode_PUM', ["alias" => "jumlahPenduduk"]);
        $this->hasOne('kode_desa', '\DesaSarana', 'kode_PUM', ["alias" => "sarana"]);
        $this->hasOne('kode_desa', '\DesaKesejahteraan', 'kode_PUM', ["alias" => "kesejahteraan"]);
        $this->hasMany('kode_desa', '\OmspanDanaDesaPagu', 'kode_desa', ["alias" => "paguDanaDesa"]);
        $this->hasMany('kode_desa', '\OmspanDanaDesaPenyaluran', 'kode_desa', ["alias" => "penyaluranDanaDesa"]);
        $this->hasMany('kode_desa', '\OmspanPenyerapanDanaDesa', 'kode_desa', ['alias' => 'penyerapan']);
        $this->hasOne('kode_desa', 'KemdagriKepadatanPendudukPerDesa', 'KODE', ['alias' => 'kkppd']);
    }

    /**
     * Returns table name mapped in the model.
     *
     * @return string
     */
    public function getSource()
    {
        return 'omspan_master_desa';
    }

    public function toDetail()
    {
        $result = $this->toArray();

        if (empty($this->kkppd)) {
            $result['penduduk'] = null;
        } else {
            $result['penduduk'] = $this->kkppd;
        }

        return $result;
    }

    public function toJsonProfile()
    {
        $result_db = $this->toArray(
            [
                "kode_desa", "nama_provinsi", "nama_pemda", "nama_kecamatan", "nama_desa"
            ]
        );

        $result = [
            'kode_PUM' => $result_db['kode_desa'],
            'provinsi' => $result_db['nama_provinsi'],
            'kabupaten_kota' => $result_db['nama_pemda'],
            'kecamatan' => $result_db['nama_kecamatan'],
            'desa_kelurahan' => $result_db['nama_desa'],
            'updated_date' => null
        ];

        if ($this->jumlahPenduduk) {
            $result["jumlah_penduduk"] = $this->jumlahPenduduk->jumlah_penduduk;
            $result["jumlah_kk"] = $this->jumlahPenduduk->jumlah_kk;
        }
        $result["sarana"] = [];
        $result["sarana"]["balai_desa"] = "Tidak Ada";
        $result["sarana"]["listrik"] = "Tidak Ada";
        $result["sarana"]["air_bersih"] = "Tidak Ada";
        if ($this->sarana) {
            $result["sarana"]["balai_desa"] = $this->sarana->balai_desa;
            $result["sarana"]["listrik"] = $this->sarana->listrik;
            $result["sarana"]["air_bersih"] = $this->sarana->air_bersih;
        }

        $result["kesejahteraan"] = [];
        $result["kesejahteraan"]["pra_sejahtera"] = 0;
        $result["kesejahteraan"]["sejahtera_1"] = 0;
        $result["kesejahteraan"]["sejahtera_2"] = 0;
        $result["kesejahteraan"]["sejahtera_3"] = 0;
        $result["kesejahteraan"]["sejahtera_3_plus"] = 0;
        $result["kesejahteraan"]["jumlah_kk"] = 0;
        if ($this->kesejahteraan) {
            $result["kesejahteraan"]["pra_sejahtera"] = $this->kesejahteraan->pra_sejahtera;
            $result["kesejahteraan"]["sejahtera_1"] = $this->kesejahteraan->sejahtera_1;
            $result["kesejahteraan"]["sejahtera_2"] = $this->kesejahteraan->sejahtera_2;
            $result["kesejahteraan"]["sejahtera_3"] = $this->kesejahteraan->sejahtera_3;
            $result["kesejahteraan"]["sejahtera_3_plus"] = $this->kesejahteraan->sejahtera_3_plus;
            $result["kesejahteraan"]["jumlah_kk"] = $this->kesejahteraan->jumlah_kk;
        }

        return $result;
    }

    public function rincianAnggaran($tahun) {
        $result_db = $this->toArray(
            [
                "kode_desa", "nama_provinsi", "nama_pemda", "nama_kecamatan", "nama_desa"
            ]
        );

        $result = [
            'kode_PUM' => $result_db['kode_desa'],
            'provinsi' => $result_db['nama_provinsi'],
            'kabupaten_kota' => $result_db['nama_pemda'],
            'kecamatan' => $result_db['nama_kecamatan'],
            'desa_kelurahan' => $result_db['nama_desa'],
            'updated_date' => null
        ];

        $result["pagu"] = 0;
        $result["status_desa"] = "-";
        $isPaguFound = false;
        if ($this->paguDanaDesa) {
            foreach ($this->paguDanaDesa as $pagu) {
                if ($pagu->tahun == $tahun) {
                    $isPaguFound = true;
                    $result["pagu"] = (!is_null($pagu->pagu) ? $pagu->pagu : 0) + (!is_null($pagu->pagu_tambahan) ? $pagu->pagu_tambahan : 0);
                    $result["status_desa"] = !is_null($pagu->status_desa) ? $pagu->status_desa : "-";
                    break;
                }
            }
        }

        $penyaluran = $this->processPenyaluran($tahun, true);
        $result["total_penyaluran"] = $penyaluran["total_penyaluran"];
        $result["penyaluran"] = $penyaluran["penyaluran"];
        $isPenyaluranFound = $penyaluran["is_penyaluran_found"];

        $isRealisasiFound = false;
        if ($this->penyerapan) {
            $result["penyerapan"] = $this->processPenyerapanKumulatif($tahun);
            $isRealisasiFound = true;
        }
        if (!$isPaguFound && !$isPenyaluranFound && !$isRealisasiFound) {
            return false;
        }
        $result["last_update"] = $this->lastUpdateData();
        return $result;
    }

    /**
     * @param $tahun
     * @param bool $withBlt
     * jika true, maka akan mengembalikan semua jenis penyaluran dana desa (BLT|REGULER|MANDIRI|etc)
     * jika false, maka hanya mengembalikan penyaluran dana desa REGULER
     * @return array|false
     */
    public function jsonDetilAnggaran($tahun, $withBlt = false)
    {
        $result_db = $this->toArray(
            [
                "kode_desa", "nama_provinsi", "nama_pemda", "nama_kecamatan", "nama_desa"
            ]
        );

        $result = [
            'kode_PUM' => $result_db['kode_desa'],
            'provinsi' => $result_db['nama_provinsi'],
            'kabupaten_kota' => $result_db['nama_pemda'],
            'kecamatan' => $result_db['nama_kecamatan'],
            'desa_kelurahan' => $result_db['nama_desa'],
            'updated_date' => null
        ];

        $result["pagu"] = 0;
        $isPaguFound = false;
        if ($this->paguDanaDesa) {
            foreach ($this->paguDanaDesa as $pagu) {
                if ($pagu->tahun == $tahun) {
                    $isPaguFound = true;
                    $result["pagu"] = $pagu->pagu;
                    break;
                }
            }
        }

        $penyaluran = $this->processPenyaluran($tahun, $withBlt);
        $result["total_penyaluran"] = $penyaluran["total_penyaluran"];
        $result["penyaluran"] = $penyaluran["penyaluran"];
        $isPenyaluranFound = $penyaluran["is_penyaluran_found"];

        $result["penyerapan"] = [];
        for ($i = 1; $i <= 3; $i++) {
            $tahap[(string)$i] = [];
            $res[(string)$i] = [];
        }

        $isRealisasiFound = false;
        if ($this->penyerapan) {
            $result["penyerapan"] = $this->processPenyerapanNonKumulatif($tahun);
            $isRealisasiFound = true;
        }
        if (!$isPaguFound && !$isPenyaluranFound && !$isRealisasiFound) {
            return false;
        }
        $result["last_update"] = $this->lastUpdateData();
        return $result;
    }

    public static function modelFromOmspanDanaDesaPagu(OmspanDanaDesaPagu $omspanDanaDesaPagu): OmspanMasterDesa
    {
        $desa = new OmspanMasterDesa();
        $desa->nama_desa = $omspanDanaDesaPagu->nama_desa;
        $desa->nama_pemda = $omspanDanaDesaPagu->pemda->nm_lokasi;
        $desa->nama_provinsi = $omspanDanaDesaPagu->pemda->provinsi->nm_prov;
        $desa->kode_desa = $omspanDanaDesaPagu->kode_desa;

        return $desa;
    }

    private function lastUpdateData() {
        if (is_array($this->updatedAt)) {
            $last = null;
            foreach ($this->updatedAt as $updatedAt) {
                if (!is_null($updatedAt)) {
                    $time = strtotime($updatedAt);
                    $date = date('Y-m-d',$time);
                    if (is_null($last) || $date > $last) {
                        $last = $date;
                    }
                }
            }
            return $last;
        } else return "-";
    }

    private function processPenyerapanKumulatif($tahun) {
        $penyerapans = OmspanPenyerapanDanaDesa::find([
            'conditions' => 'kode_desa = :kode_desa: and tahun = :tahun:',
            'bind' => ['kode_desa' => $this->kode_desa, 'tahun' => $tahun]
        ]);
        $res = $uraians = $kegiatans = $bidangs = [];
        foreach ($penyerapans as $penyerapan) {
            /** @var OmspanPenyerapanDanaDesa $penyerapan */
            $uraianOutput = $penyerapan->uraianOutput;
            $uraians[$uraianOutput->kode] = $uraianOutput->uraian;
            $kegiatan = $uraianOutput->kegiatan;
            $kegiatans[$kegiatan->kode] = $kegiatan->nama;
            $bidang = $kegiatan->bidang;
            $bidangs[$bidang->kode] = $bidang->nama;
            if (!array_key_exists($bidang->kode, $res)) {
                $res[$bidang->kode] = [];
            }
            if (!array_key_exists($kegiatan->kode, $res[$bidang->kode])) {
                $res[$bidang->kode][$kegiatan->kode] = [];
            }
            if (!array_key_exists($uraianOutput->kode, $res[$bidang->kode][$kegiatan->kode])) {
                $res[$bidang->kode][$kegiatan->kode][$uraianOutput->kode] = [];
            }
            $rincian = [
                "volume" => $penyerapan->volume,
                "satuan_output" => $penyerapan->satuan_output,
                "keterangan" => $penyerapan->keterangan,
                "realisasi" => $penyerapan->getRealisasi(),
            ];
            $res[$bidang->kode][$kegiatan->kode][$uraianOutput->kode][] = $rincian;
        }

        $result = [];
        foreach ($res as $key => $bidang) {
            $current = [
                "bidang" => $bidangs[$key],
                "kegiatans" => []
            ];
            foreach ($bidang as $keyy => $kegiatan) {
                $currentt = [
                    "kegiatan" => $kegiatans[$keyy],
                    "uraians" => []
                ];
                foreach ($kegiatan as $keyyy => $uraian) {
                    $currenttt = [
                        "uraian" => $uraians[$keyyy],
                        "rincian" => $res[$key][$keyy][$keyyy]
                    ];
                    $currentt["uraians"][] = $currenttt;
                }
                $current["kegiatans"][] = $currentt;
            }
            $result[] = $current;
        }

        return $result;
    }

    private function processPenyerapanNonKumulatif($tahun) {
        $res = $tahap = [];
        for ($i = 1; $i <= 3; $i++) {
            $tahap[(string)$i] = [];
            $res[(string)$i] = [];
        }

        foreach ($this->penyerapan as $realisasi) {
            if ($realisasi->tahun == $tahun) {
                $this->updatedAt[] = $realisasi->updated_at;
                $uraianOutput = $realisasi->uraianOutput;
                $kegiatan = $uraianOutput->kegiatan;
                $bidang = $kegiatan->bidang;
                for ($i = 1; $i <= 3; $i++) {
                    $field = "realisasi_tahap_" . $i;
                    $percentField = "persentase_" . $field;
                    if ($realisasi->$field > 0) {
                        $tahap[(string)$i][$bidang->kode]["nama"] = $bidang->nama;
                        $tahap[(string)$i][$bidang->kode][$kegiatan->kode]["nama"] = $kegiatan->nama;
                        if (!array_key_exists($uraianOutput->kode, $tahap[(string)$i][$bidang->kode][$kegiatan->kode])) {
                            $tahap[(string)$i][$bidang->kode][$kegiatan->kode][$uraianOutput->kode] = [];
                        }
                        $uraianDetail = [
                            "nama" => $uraianOutput->uraian,
                            "realisasi" => $realisasi->$field,
                            "keterangan" => $realisasi->keterangan
                        ];
                        if (empty($realisasi->$percentField)) {
                            $uraianDetail["anggaran"] = 0;
                            $uraianDetail["persentase"] = 0;
                        } else {
                            $uraianDetail["anggaran"] = $realisasi->$field * 100 / $realisasi->$percentField;
                            $uraianDetail["persentase"] = $realisasi->$percentField;
                        }
                        $tahap[(string)$i][$bidang->kode][$kegiatan->kode][$uraianOutput->kode][] = $uraianDetail;
                    }
                }
            }
        }

        for ($i = 1; $i <= 3; $i++) {
            foreach ($tahap[(string)$i] as $tahapKey => $tahapValue) {
                $bidangElm = [];
                foreach ($tahapValue as $bidangKey => $bidangValue) {
                    if ($bidangKey != "nama") {
                        $kegiatanElm = [];
                        foreach ($bidangValue as $kegiatanKey => $kegiatanValue) {
                            if ($kegiatanKey != "nama") {
                                foreach ($kegiatanValue as $itemKegiatan) {
                                    if (!isset($kegiatanElm["uraian"])) {
                                        $kegiatanElm["uraian"] = [];
                                    }
                                    $kegiatanElm["uraian"][] = $itemKegiatan;
                                }
                            } else {
                                $kegiatanElm["nama"] = $kegiatanValue;
                            }
                        }
                        $bidangElm["kegiatan"][] = $kegiatanElm;
                    } else {
                        $bidangElm["nama"] = $bidangValue;
                    }
                }

                $res[$i][] = $bidangElm;
            }
        }

        return $res;
    }

    private function processPenyaluran($tahun, $withBlt) {
        $result = [
            "total_penyaluran" => 0,
            "penyaluran" => [],
            "is_penyaluran_found" => false
        ];
        for ($i = 1; $i < 4; $i++) {
            if (!$withBlt) {
                $result["penyaluran"][(string)$i] = [
                    "realisasi" => 0,
                    "tanggal_realisasi" => ""
                ];
            } else {
                $result["penyaluran"][(string)$i] = [];
            }
        }
        foreach ($this->penyaluranDanaDesa as $penyaluran) {
            if ($penyaluran->tahun == $tahun) {
                $result["is_penyaluran_found"] = true;
                $this->updatedAt[] = $penyaluran->updated_at;
                // utk akomodir FE versi lama dmn asumsinya 1 tahap penyaluran = 1x realisasi
                if (!$withBlt) {
                    $result["total_penyaluran"] += $penyaluran->realisasi;
                    $result["penyaluran"][$penyaluran->tahap]["realisasi"] = $penyaluran->realisasi;
                    $result["penyaluran"][$penyaluran->tahap]["tanggal_realisasi"] = $penyaluran->tanggal_sp2d;
                } else {
                    $result["total_penyaluran"] += $penyaluran->realisasi;
                    $realisasi = [
                        'realisasi' => $penyaluran->realisasi,
                        'tanggal_realisasi' => $penyaluran->tanggal_sp2d,
                        'no_sp2d' => $penyaluran->no_sp2d
                    ];
                    $result["penyaluran"][$penyaluran->tahap][] = $realisasi;
                }
            }
        }
        for ($i = 1; $i < 4; $i++) {
            if ($withBlt) {
                usort($result["penyaluran"][(string)$i], function($a, $b) {
                    return strnatcasecmp($a["no_sp2d"], $b["no_sp2d"]);
                });
            }
        }
        return $result;
    }

    private function emptyValueForTahapCheck(OmspanPenyerapanDanaDesa $penyerapan, $key, $tahun, $totalTahap, $tahap) {
        if (!empty($penyerapan->created_at) && date('Y-m-d', strtotime($penyerapan->created_at)) < $this->cutOffTahap($totalTahap, $tahun)[$tahap - 2]) {
            return false;
        } else {
            return empty($penyerapan->$key) || $penyerapan->$key == "0" || $penyerapan->$key == "";
        }
    }

    private function cutOffTahap($totalTahap, $tahun) {
        if ($totalTahap == 2) {
            return [
                date('Y-m-d', strtotime($tahun . '-06-30'))
            ];
        } else if ($totalTahap == 3) {
            return [
                date('Y-m-d', strtotime($tahun.'-04-30')),
                date('Y-m-d', strtotime($tahun.'-08-31'))
            ];
        } else {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Total tahap tidak valid!");
        }
    }
}
