<?php

namespace App\Controllers\Panel\Ujian\Jadwal\Detail;

use App\Controllers\Panel\BC;
use App\Models\Panel\Ujian\Hasil;
use App\Models\Panel\Ujian\Jadwal;
use CodeIgniter\API\ResponseTrait;
use Predis\Client;

class Main extends BC
{
    use ResponseTrait;
    private $pgcmsd = [];
    private $pgcmsud = [];
    private $pgmsd = [];
    private $pgmsud = [];
    private $pgcsd = [];
    private $pgcsud = [];
    private $jadwalModel, $jawaban_pg, $jawaban_pgmulti, $jawaban_pgtf, $jawaban_pgcouple, $jawaban_shortentry, $jawaban_esai, $redis, $trxRedis;
    public function __construct()
    {
        parent::__construct();
        $this->jadwalModel = new Jadwal();
    }
    public function index($id)
    {
        $id = base64_decode($id);
        $jadwalData = $this->jadwalModel->findId($id);
        if (!$jadwalData) return view('Utils/404', ['code' => 404, 'text' => 'Jadwal Tidak Ditemukan']);
        $data['page_title'] = $jadwalData['nama'] . " - " . $jadwalData['kode_ruang'];
        $data['jadwalData'] = $jadwalData;
        return view('Panel/Ujian/Jadwal/Detail/index', $data);
    }
    public function status($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $id = base64_decode($id);
        $jadwalData = $this->jadwalModel->findId($id);
        if (!$jadwalData) return $this->failNotFound();
        $data['jenis_ujian'] = $jadwalData['kode_jenis'];
        $data['status'] = $jadwalData['status'];
        $data['token'] = $jadwalData['token'];
        $data['use_token'] = $jadwalData['use_token'];
        $data['nama'] = $jadwalData['nama'];
        $data['nama_draft'] = $jadwalData['nama_draft'];
        $data['startDateTime'] = $jadwalData['startDateTime'];
        $data['endDateTime'] = $jadwalData['endDateTime'];
        $data['belum_ujian'] = count($this->jadwalModel->unstarted_siswa($id));
        $data['sedang_ujian'] = count($this->jadwalModel->ongoing_siswa($id));
        $data['sudah_ujian'] = count($this->jadwalModel->finished_siswa($id));
        return $this->respond($data);
    }
    public function extra_time($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $id = base64_decode($id);
        $jadwalData = $this->jadwalModel->findId($id);
        if (!$jadwalData) return $this->failNotFound();
        $d = (array) $this->request->getVar('data');
        if (!$d) return $this->failForbidden();
        $data = [];
        $ids = [];
        foreach ($d as $dd) {
            $ids[] = $dd->id;
        }
        $db  = db_connect();
        $db->transStart();
        $uj = $db->table('ujian_siswa')->select('id,end_at,status')->whereIn('status', ['1', '2'])->whereIn('id', $ids)->get()->getResultArray();

        $this->jawaban_pg = $db->table('jawaban_pg_ujian_siswa')->whereIn('ujian_id', $ids)->get()->getResultArray();
        $this->jawaban_pgtf = $db->table('jawaban_pgtf_ujian_siswa')->whereIn('ujian_id', $ids)->get()->getResultArray();
        $this->jawaban_pgmulti = $db->table('jawaban_pgmulti_ujian_siswa')->whereIn('ujian_id', $ids)->get()->getResultArray();
        $this->jawaban_pgcouple = $db->table('jawaban_pgcouple_ujian_siswa')->whereIn('ujian_id', $ids)->get()->getResultArray();
        $this->jawaban_shortentry = $db->table('jawaban_shortentry_ujian_siswa')->whereIn('ujian_id', $ids)->get()->getResultArray();
        $this->jawaban_esai = $db->table('jawaban_esai_ujian_siswa')->whereIn('ujian_id', $ids)->get()->getResultArray();

        if (redison()) {
            try {
                $redis  = json_decode(options('redis-config'), true);
                $this->redis = new Client([
                    'scheme' => 'tcp',
                    'host'   => $redis['host'],
                    'port'   => $redis['port'],
                    'password' => $redis['password'],
                    'database' => $redis['database'],
                ]);
                $this->redis->connect();
            } catch (\Throwable $th) {
                return $this->failServerError(ENVIRONMENT != 'production' ? $th->getMessage() : "Gagal koneksi ke redis");
            }
            $this->trxRedis = $this->redis->transaction();
        }
        foreach ($uj as $u) {
            foreach ($d as $dd) {
                if ($dd->id == $u['id']) {
                    $extraTime = $u['end_at'] + $dd->extra_time * 60;
                    if ($extraTime > $jadwalData['endDateTime']) $extraTime = $jadwalData['endDateTime'];
                    $data[] = [
                        'id' => $u['id'],
                        'end_at' => $extraTime,
                        'status' => 1
                    ];
                    if ($u['status'] != '2') continue;
                    if (redison()) {
                        foreach ($this->jawaban_pg as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            $this->trxRedis->set("jawaban_pg_ujian_siswa-$u[id]-$jpv[soal_id]", $jpv['opsi_id']);
                            $db->table('jawaban_pg_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                        }
                        $pgmulti = [];
                        foreach ($this->jawaban_pgmulti as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            if (!isset($pgmulti[$jpv['soal_id']])) $pgmulti[$jpv['soal_id']] = [];
                            $pgmulti[$jpv['soal_id']][] = $jpv['opsi_id'];
                        }
                        foreach ($pgmulti as $kpgm => $vpgm) {
                            $this->trxRedis->set("jawaban_pgmulti_ujian_siswa-$u[id]-$kpgm", implode(',', $vpgm));
                            $db->table('jawaban_pgmulti_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgm])->delete();
                        }

                        $pgtf = [];
                        foreach ($this->jawaban_pgtf as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            if (!isset($pgtf[$jpv['soal_id']])) $pgtf[$jpv['soal_id']] = [];
                            $pgtf[$jpv['soal_id']][] = "$jpv[opsi_id]-$jpv[tf]";
                        }
                        foreach ($pgtf as $kpgtf => $vpgtf) {
                            $db->table('jawaban_pgtf_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgtf])->delete();
                            $this->trxRedis->set("jawaban_pgtf_ujian_siswa-$u[id]-$kpgtf", implode(',', $vpgtf));
                        }
                        $pgcouple = [];
                        foreach ($this->jawaban_pgcouple as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            if (!isset($pgcouple[$jpv['soal_id']])) $pgcouple[$jpv['soal_id']] = [];
                            $pgcouple[$jpv['soal_id']][] = "$jpv[couple_id]-$jpv[opsi_id]";
                        }
                        foreach ($pgcouple as $kpgcouple => $vpgcouple) {
                            $db->table('jawaban_pgcouple_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgcouple])->delete();
                            $this->trxRedis->set("jawaban_pgcouple_ujian_siswa-$u[id]-$kpgcouple", implode(',', $vpgcouple));
                        }
                        foreach ($this->jawaban_shortentry as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            $db->table('jawaban_shortentry_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                            $this->trxRedis->set("jawaban_shortentry_ujian_siswa-$u[id]-$jpv[soal_id]", $jpv['respond']);
                        }
                        foreach ($this->jawaban_esai as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            $db->table('jawaban_esai_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                            $this->trxRedis->set("jawaban_esai_ujian_siswa-$u[id]-$jpv[soal_id]", $jpv['esai']);
                        }
                    } else {
                        foreach ($this->jawaban_pg as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            $db->table('jawaban_pg_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                            $db->table('jawaban_pg_temp_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                            $db->table('jawaban_pg_temp_ujian_siswa')->set($jpv)->insert();
                        }
                        $pgmulti = [];
                        foreach ($this->jawaban_pgmulti as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            if (!isset($pgmulti[$jpv['soal_id']])) $pgmulti[$jpv['soal_id']] = [];
                            $pgmulti[$jpv['soal_id']][] = $jpv['opsi_id'];
                        }
                        $deletedPGMULTI = [];
                        foreach ($pgmulti as $kpgm => $vpgm) {
                            if (!isset($deletedPGMULTI[$u['id'] . $kpgm])) {
                                $deletedPGMULTI[$u['id'] . $kpgm] = true;
                                $db->table('jawaban_pgmulti_temp_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgm])->delete();
                                $db->table('jawaban_pgmulti_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgm])->delete();
                            }
                            $vvpgm = [];
                            foreach ($vpgm as $k => $v) {
                                $vvpgm[] = [
                                    'ujian_id' => $u['id'],
                                    'soal_id' => $kpgm,
                                    'opsi_id' => $v,
                                    'created_at' => time(),
                                ];
                            }
                            if (!$vvpgm) $vvpgm[] = [
                                'ujian_id' => $u['id'],
                                'soal_id' => $kpgm,
                                'opsi_id' => null,
                                'created_at' => time(),
                            ];
                            $db->table('jawaban_pgmulti_temp_ujian_siswa')->insertBatch($vvpgm);
                        }

                        $pgtf = [];
                        foreach ($this->jawaban_pgtf as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            if (!isset($pgtf[$jpv['soal_id']])) $pgtf[$jpv['soal_id']] = [];
                            $pgtf[$jpv['soal_id']][] = "$jpv[opsi_id]-$jpv[tf]";
                        }
                        $deletedPGTF = [];
                        foreach ($pgtf as $kpgtf => $vpgtf) {
                            if (!isset($deletedPGTF[$u['id'] . $kpgtf])) {
                                $deletedPGTF[$u['id'] . $kpgtf] = true;
                                $db->table('jawaban_pgtf_temp_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgtf])->delete();
                                $db->table('jawaban_pgtf_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgtf])->delete();
                            }
                            $vvpgtf = [];
                            foreach ($vpgtf as $k => $v) {
                                $vvpgtf[] = [
                                    'ujian_id' => $u['id'],
                                    'soal_id' => $kpgtf,
                                    'opsi_id' => $v,
                                    'created_at' => time(),
                                ];
                            }
                            if (!$vvpgtf) $vvpgtf[] = [
                                'ujian_id' => $u['id'],
                                'soal_id' => $kpgtf,
                                'opsi_id' => null,
                                'created_at' => time(),
                            ];
                            $db->table('jawaban_pgtf_temp_ujian_siswa')->insertBatch($vvpgtf);
                        }
                        $pgcouple = [];
                        foreach ($this->jawaban_pgcouple as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            if (!isset($pgcouple[$jpv['soal_id']])) $pgcouple[$jpv['soal_id']] = [];
                            $pgcouple[$jpv['soal_id']][] = "$jpv[couple_id]-$jpv[opsi_id]";
                        }
                        $deletedPGCOUPLE = [];
                        foreach ($pgcouple as $kpgcouple => $vpgcouple) {
                            if (!isset($deletedPGCOUPLE[$u['id'] . $kpgcouple])) {
                                $deletedPGCOUPLE[$u['id'] . $kpgcouple] = true;
                                $db->table('jawaban_pgcouple_temp_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgcouple])->delete();
                                $db->table('jawaban_pgcouple_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $kpgcouple])->delete();
                            }
                            $vvpgcouple = [];
                            foreach ($vpgcouple as $k => $v) {
                                $vvpgcouple[] = [
                                    'ujian_id' => $u['id'],
                                    'soal_id' => $kpgcouple,
                                    'opsi_id' => $v,
                                    'created_at' => time(),
                                ];
                            }
                            if (!$vvpgcouple) $vvpgcouple[] = [
                                'ujian_id' => $u['id'],
                                'soal_id' => $kpgcouple,
                                'opsi_id' => null,
                                'created_at' => time(),
                            ];
                            $db->table('jawaban_pgcouple_temp_ujian_siswa')->insertBatch($vvpgcouple);
                        }
                        foreach ($this->jawaban_shortentry as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            $db->table('jawaban_shortentry_temp_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                            $db->table('jawaban_shortentry_temp_ujian_siswa')->set($jpv)->insert();
                            $db->table('jawaban_shortentry_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                        }
                        foreach ($this->jawaban_esai as $jpk => $jpv) {
                            if ($jpv['ujian_id'] != $u['id']) continue;
                            $db->table('jawaban_esai_temp_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                            $db->table('jawaban_esai_temp_ujian_siswa')->set($jpv)->insert();
                            $db->table('jawaban_esai_ujian_siswa')->where(['ujian_id' => $u['id'], 'soal_id' => $jpv['soal_id']])->delete();
                        }
                    }
                    break;
                }
            }
        }
        if (!$data) return $this->fail(['message' => "Gagal Menambahkan Waktu"]);
        $state = $db->table("ujian_siswa")->whereIn('status', ['1', '2'])->updateBatch($data, 'id');
        $db->transComplete();
        if (!$state) return $this->fail(['message' => "Gagal Menambahkan Waktu"]);
        if (redison()) $this->trxRedis->execute();
        return $this->respond(['message' => "Berhasil Menambahkan Waktu"]);
    }
    public function peserta($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $id = base64_decode($id);
        $data = $this->jadwalModel->peserta($id);
        return $this->respond(['data' => $data]);
    }
    public function simpanPeserta($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $id = base64_decode($id);
        $peserta = $this->request->getVar('peserta');
        if (!$this->request->getVar('force-save')) {
            $runningSiswa = db_connect()->table('ujian_siswa us')->select('ms.nama,ms.nomor_induk');
            $runningSiswa->join('m_siswa ms', 'ms.id=us.siswa_id')->where(['us.jadwal_id' => $id, 'us.status !=' => '0']);
            if ($peserta) $runningSiswa->whereNotIn('ms.id', $peserta);
            $runningSiswa = $runningSiswa->get()->getResultArray();
            if ($runningSiswa) {
                $err = 'Siswa sudah memulai ujian, ini akan menghapus nilai yang sudah ada!';
                $errs = [];
                foreach ($runningSiswa as $key => $v) {
                    $errs[] =  $v['nomor_induk'] . "/" . $v['nama'];
                }
                $err = $err . implode(',', $errs);
                return $this->fail(['csrf' => csrf_hash(), 'message' => $err, 'confirmation' => true], 403);
            }
        }
        $state = $this->jadwalModel->simpanPeserta($id, $peserta);
        if ($state) {
            return $this->respond(['message' => 'Berhasil Menyimpan']);
        }
        return $this->respond(['message' => 'Gagal Menyimpan']);
    }
    // public function reset($jid, $ujian_id)
    // {
    //     if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
    //         exit('No direct script access allowed');
    //     }
    //     $state = (new Hasil())->reset(base64_decode($ujian_id), base64_decode($jid));
    //     return $this->respond(['reseted' => $state, 'message' => $state ? "Berhasil Reset" : "Gagal Reset"]);
    // }
    // public function reset_batch($jid)
    // {
    //     if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
    //         exit('No direct script access allowed');
    //     }
    //     $state = (new Hasil())->reset_batch($this->request->getVar('id'), base64_decode($jid));
    //     return $this->respond(['reseted' => $state, 'message' => $state ? "Berhasil Reset" : "Gagal Reset"]);
    // }
    public function unlock($jid, $ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $state = (new Hasil())->unlock(base64_decode($ujian_id), base64_decode($jid));
        return $this->respond(['unlocked' => $state, 'message' => $state ? "Berhasil Buka" : "Gagal Buka"]);
    }
    public function unlock_batch($jid)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $state = (new Hasil())->unlock_batch($this->request->getVar('id'), base64_decode($jid));
        return $this->respond(['unlocked' => $state, 'message' => $state ? "Berhasil Buka" : "Gagal Buka"]);
    }
    public function finish_batch($jid)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $db = db_connect();
        if (redison()) {
            try {
                $redis  = json_decode(options('redis-config'), true);
                $this->redis = new Client([
                    'scheme' => 'tcp',
                    'host'   => $redis['host'],
                    'port'   => $redis['port'],
                    'password' => $redis['password'],
                    'database' => $redis['database'],
                ]);
                $this->redis->connect();
            } catch (\Throwable $th) {
                return $this->failServerError(ENVIRONMENT != 'production' ? $th->getMessage() : "Gagal koneksi ke redis");
            }
            $keyJPG = [];
            $keyJPGC = [];
            $keyJE = [];
            $keyJSE = [];
            $keyJPGM = [];
            $keyJPGTF = [];
            foreach ($this->request->getVar('id') as $k => $ujian_id) {
                $keyJPG = $this->redis->keys("jawaban_pg_ujian_siswa-$ujian_id-*");
                $sid = [];
                $rsid = [];
                foreach ($keyJPG as $jpg) {
                    $ssid = explode('-', $jpg)[2];
                    $rsid[] = "soal-$ssid";
                    $sid[] = $ssid;
                }
                $jawaban_pg = [];

                if ($keyJPG) {
                    foreach ($this->redis->mget($keyJPG) as $k => $rs) {
                        $jawaban_pg[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'opsi_id' => is_numeric($rs) ? $rs : null,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];
                    }
                }
                if ($jawaban_pg) {
                    $db->table('jawaban_pg_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                    $db->table('jawaban_pg_ujian_siswa')->insertBatch($jawaban_pg);
                }
            }

            $keyJPGM = $this->redis->keys("jawaban_pgmulti_ujian_siswa-$ujian_id-*");
            $sid = [];
            $rsid = [];
            foreach ($keyJPGM as $jpg) {
                $ssid = explode('-', $jpg)[2];
                $rsid[] = "soal-$ssid";
                $sid[] = $ssid;
            }
            $jawaban_pgmulti = [];
            if ($keyJPGM) {
                foreach ($this->redis->mget($keyJPGM) as $k => $rs) {
                    foreach (explode(',', $rs) as $srs) {
                        $jawaban_pgmulti[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'opsi_id' => is_numeric($srs) ? $srs : null,
                            'created_at' => time(),
                        ];
                    }
                }
            }
            if ($jawaban_pgmulti) {
                $db->table('jawaban_pgmulti_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                $db->table('jawaban_pgmulti_ujian_siswa')->insertBatch($jawaban_pgmulti);
            }


            $keyJPGTF = $this->redis->keys("jawaban_pgtf_ujian_siswa-$ujian_id-*");
            $sid = [];
            $rsid = [];
            foreach ($keyJPGTF as $jpg) {
                $ssid = explode('-', $jpg)[2];
                $rsid[] = "soal-$ssid";
                $sid[] = $ssid;
            }
            $jawaban_pgtf = [];
            if ($keyJPGTF) {
                foreach ($this->redis->mget($keyJPGTF) as $k => $rs) {
                    foreach (explode(',', $rs) as $srs) {
                        $jawaban_pgtf[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'opsi_id' => explode('-', $srs)[0] ?? null,
                            'tf' => explode('-', $srs)[1] ?? null,
                            'created_at' => time(),
                        ];
                    }
                }
            }
            if ($jawaban_pgtf) {
                $db->table('jawaban_pgtf_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                $db->table('jawaban_pgtf_ujian_siswa')->insertBatch($jawaban_pgtf);
            }


            $keyJPGC = $this->redis->keys("jawaban_pgcouple_ujian_siswa-$ujian_id-*");
            $sid = [];
            $rsid = [];
            foreach ($keyJPGC as $jpg) {
                $ssid = explode('-', $jpg)[2];
                $rsid[] = "soal-$ssid";
                $sid[] = $ssid;
            }
            $jawaban_pgcouple = [];
            if ($keyJPGC) {
                foreach ($this->redis->mget($keyJPGC) as $k => $rs) {
                    foreach (explode(',', $rs) as $srs) {
                        $jawaban_pgcouple[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'couple_id' => explode('-', $srs)[0] ?? null,
                            'opsi_id' => explode('-', $srs)[1] ?? null,
                            'created_at' => time(),
                        ];
                    }
                }
            }
            if ($jawaban_pgcouple) {
                $db->table('jawaban_pgcouple_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                $db->table('jawaban_pgcouple_ujian_siswa')->insertBatch($jawaban_pgcouple);
            }


            $keyJSE = $this->redis->keys("jawaban_shortentry_ujian_siswa-$ujian_id-*");
            $sid = [];
            $rsid = [];
            foreach ($keyJSE as $jpg) {
                $ssid = explode('-', $jpg)[2];
                $rsid[] = "soal-$ssid";
                $sid[] = $ssid;
            }
            $jawaban_shortentry = [];
            if ($keyJSE) {
                foreach ($this->redis->mget($keyJSE) as $k => $rs) {
                    foreach (explode(',', $rs) as $srs) {
                        $jawaban_shortentry[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'respond' => $srs,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];
                    }
                }
            }
            if ($jawaban_shortentry) {
                $je = [];
                foreach ($jawaban_shortentry as $kje => $vje) {
                    $id = $vje['ujian_id'] . $vje['soal_id'];
                    if (!isset($je[$id])) {
                        $je[$id] = $vje;
                        continue;
                    }
                    $je[$id]['respond'] .= ",$vje[respond]";
                }
                $jawaban_shortentry = [];
                foreach ($je as $k => $v) {
                    $jawaban_shortentry[] = $v;
                }
                $db->table('jawaban_shortentry_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                $db->table('jawaban_shortentry_ujian_siswa')->insertBatch($jawaban_shortentry);
            }


            $keyJE = $this->redis->keys("jawaban_esai_ujian_siswa-$ujian_id-*");
            $sid = [];
            $rsid = [];
            foreach ($keyJE as $jpg) {
                $ssid = explode('-', $jpg)[2];
                $rsid[] = "soal-$ssid";
                $sid[] = $ssid;
            }
            $jawaban_esai = [];
            if ($keyJE) {
                foreach ($this->redis->mget($keyJE) as $k => $rs) {
                    foreach (explode(',', $rs) as $srs) {
                        $jawaban_esai[] = [
                            'ujian_id' => $ujian_id,
                            'soal_id' => $sid[$k],
                            'esai' => $srs,
                            'created_at' => time(),
                            'updated_at' => time(),
                        ];
                    }
                }
            }
            if ($jawaban_esai) {
                $je = [];
                foreach ($jawaban_esai as $kje => $vje) {
                    $id = $vje['ujian_id'] . $vje['soal_id'];
                    if (!isset($je[$id])) {
                        $je[$id] = $vje;
                        continue;
                    }
                    $je[$id]['esai'] .= ",$vje[esai]";
                }
                $jawaban_esai = [];
                foreach ($je as $k => $v) {
                    $jawaban_esai[] = $v;
                }
                $db->table('jawaban_esai_ujian_siswa')->where('ujian_id', $ujian_id)->delete();
                $db->table('jawaban_esai_ujian_siswa')->insertBatch($jawaban_esai);
            }
        } else {
            $us = $db->table('ujian_siswa')->whereIn('id', $this->request->getVar('id'))->get()->getResultArray();
            $db->transStart();
            foreach ($us as $uk => $uv) {
                $pg = $db->table('jawaban_pg_temp_ujian_siswa')->where('ujian_id', $uv['id'])->get()->getResultArray();
                if ($pg) {
                    $db->table('jawaban_pg_temp_ujian_siswa')->where('ujian_id', $uv['id'])->delete();
                    $db->table('jawaban_pg_ujian_siswa')->insertBatch($pg);
                }
                $pgmulti = $db->table('jawaban_pgmulti_temp_ujian_siswa')->where('ujian_id', $uv['id'])->get()->getResultArray();
                if ($pgmulti) {
                    $db->table('jawaban_pgmulti_temp_ujian_siswa')->where('ujian_id', $uv['id'])->delete();
                    $db->table('jawaban_pgmulti_ujian_siswa')->insertBatch($pgmulti);
                }
                $pgcouple = $db->table('jawaban_pgcouple_temp_ujian_siswa')->where('ujian_id', $uv['id'])->get()->getResultArray();
                if ($pgcouple) {
                    $db->table('jawaban_pgcouple_temp_ujian_siswa')->where('ujian_id', $uv['id'])->delete();
                    $db->table('jawaban_pgcouple_ujian_siswa')->insertBatch($pgcouple);
                }
                $pgtf = $db->table('jawaban_pgtf_temp_ujian_siswa')->where('ujian_id', $uv['id'])->get()->getResultArray();
                if ($pgtf) {
                    $db->table('jawaban_pgtf_temp_ujian_siswa')->where('ujian_id', $uv['id'])->delete();
                    $db->table('jawaban_pgtf_ujian_siswa')->insertBatch($pgtf);
                }
                $shortentry = $db->table('jawaban_shortentry_temp_ujian_siswa')->where('ujian_id', $uv['id'])->get()->getResultArray();
                if ($shortentry) {
                    $db->table('jawaban_shortentry_temp_ujian_siswa')->where('ujian_id', $uv['id'])->delete();
                    $db->table('jawaban_shortentry_ujian_siswa')->insertBatch($shortentry);
                }
                $esai = $db->table('jawaban_esai_temp_ujian_siswa')->where('ujian_id', $uv['id'])->get()->getResultArray();
                if ($esai) {
                    $db->table('jawaban_esai_temp_ujian_siswa')->where('ujian_id', $uv['id'])->delete();
                    $db->table('jawaban_esai_ujian_siswa')->insertBatch($esai);
                }
            }
            $db->transComplete();
            if ($db->transStatus() === FALSE) return $this->respond(['finished' => false, 'message' =>  "Gagal Selesaikan"]);
        }
        $state = (new Hasil())->finish($this->request->getVar('id'), base64_decode($jid), ['status' => ['1', '2']]);
        return $this->respond(['finished' => $state, 'message' => $state ? "Berhasil Selesaikan" : "Gagal Selesaikan"]);
    }

    public function token($jid)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $token = $this->jadwalModel->resetToken(base64_decode($jid));
        if (!$token) return $this->failForbidden();
        return $this->respond(['token' => $token]);
    }

    public function progress($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $opt = [];
        $kelas = $this->request->getVar('kelas');
        $status = $this->request->getVar('status');
        if ($kelas && $kelas != 'all') $opt['kelas_id'] = $kelas;
        if ($status != null && !in_array($status, ['all', '3'])) $opt['status'] = $status;
        $data = $this->jadwalModel->progress(base64_decode($id), null, $opt);
        return $this->respond(['data' => $data, 'csrf' => ['name' => csrf_token(), 'value' => csrf_hash()]]);
    }

    public function jawaban($jadwal_id, $ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $jid = base64_decode($jadwal_id);
        $uid = base64_decode($ujian_id);
        $jadwalData = $this->jadwalModel->findId($jid);
        if (!$jadwalData) return $this->failNotFound();
        $hasilModel = new Hasil();
        $status_ujian = false;
        $data['jawaban'] = ['pg' => [], 'pgmulti' => [], 'pgcouple' => [], 'shortentry' => [], 'esai' => []];
        //pg
        $data['jawaban']['pg']['soal'] = $hasilModel->jawaban_pg($uid, $jid);
        $soal_id = [];
        foreach ($data['jawaban']['pg']['soal'] as $value) {
            $status_ujian = $value['status_ujian'] == 2;
            $soal_id[] = $value['soal_id'];
        }
        $data['jawaban']['pg']['opsi'] = $soal_id ? $hasilModel->get_soal_opsi($soal_id, $status_ujian) : $soal_id;

        //pgmulti
        $data['jawaban']['pgmulti']['soal'] = $hasilModel->jawaban_pgmulti($uid, $jid);
        $soal_id = [];
        foreach ($data['jawaban']['pgmulti']['soal'] as $value) {
            $status_ujian = $value['status_ujian'] == 2;
            $soal_id[] = $value['soal_id'];
        }
        $data['jawaban']['pgmulti']['opsi'] = $soal_id ? $hasilModel->get_soal_opsi($soal_id, $status_ujian) : $soal_id;

        //pgtf
        $data['jawaban']['pgtf']['soal'] = $hasilModel->jawaban_pgtf($uid, $jid);
        $soal_id = [];
        foreach ($data['jawaban']['pgtf']['soal'] as $value) {
            $status_ujian = $value['status_ujian'] == 2;
            $soal_id[] = $value['soal_id'];
        }
        $data['jawaban']['pgtf']['opsi'] = $soal_id ? $hasilModel->get_soal_opsi($soal_id, $status_ujian) : $soal_id;

        //pgcouple
        $data['jawaban']['pgcouple']['soal'] = $hasilModel->jawaban_pgcouple($uid, $jid);
        $soal_id = [];
        foreach ($data['jawaban']['pgcouple']['soal'] as $value) {
            $status_ujian = $value['status_ujian'] == 2;
            $soal_id[] = $value['soal_id'];
        }
        $data['jawaban']['pgcouple']['couple'] = $soal_id ? $hasilModel->get_soal_couple($soal_id, $status_ujian) : $soal_id;
        $data['jawaban']['pgcouple']['opsi'] = $soal_id ? $hasilModel->get_soal_opsi($soal_id, $status_ujian) : $soal_id;
        //shortentry
        $data['jawaban']['shortentry']['soal'] = $hasilModel->jawaban_shortentry($uid, $jid, true);

        //esai
        $data['jawaban']['esai']['soal'] = $hasilModel->jawaban_esai($uid, $jid);
        $data['csrf'] = csrf_hash();
        return $this->respond($data);
    }
    public function save_jawaban($jadwal_id, $ujian_id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $id = base64_decode($jadwal_id);
        $jadwalData = $this->jadwalModel->findId($id);
        if (!$jadwalData) return $this->failNotFound();
        $hasilModel = new Hasil();
        $state = false;
        $esai = $this->request->getVar('esai');
        $shortentry = $this->request->getVar('shortentry');
        $pg = $this->request->getVar('pg');
        $pgmulti = $this->request->getVar('pgmulti');
        $pgtf = $this->request->getVar('pgtf');
        $pgcouple = $this->request->getVar('pgcouple');
        if ($pg) $state = $hasilModel->save_jawaban_pg((array)$pg, $ujian_id);
        if ($pgmulti) $state = $hasilModel->save_jawaban_pgmulti((array)$pgmulti, $ujian_id);
        if ($pgtf) $state = $hasilModel->save_jawaban_pgtf((array)$pgtf, $ujian_id);
        if ($pgcouple) $state = $hasilModel->save_jawaban_pgcouple((array)$pgcouple, $ujian_id);
        if ($shortentry) $state = $hasilModel->save_jawaban_shortentry((array) $shortentry, $ujian_id);
        if ($esai) $state = $hasilModel->save_jawaban_esai((array)$esai, $ujian_id);
        if (!$state) return $this->fail(['message' => 'Gagal menyimpan jawaban', 'csrf' => csrf_hash()]);
        return $this->respond(['message' => "Berhasil menyimpan jawaban",  'csrf' => csrf_hash()]);
    }
}
