<?php

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

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

class Generator extends BC
{
    use ResponseTrait;
    private $jawaban_pg = [];
    private $jawaban_pgmulti = [];
    private $jawaban_pgtf = [];
    private $jawaban_pgcouple = [];
    private $jawaban_shortentry = [];
    private $jawaban_esai = [];
    private $soal_pg = [];
    private $soal_pgmulti = [];
    private $soal_pgtf = [];
    private $soal_pgcouple = [];
    private $soal_shortentry = [];
    private $soal_esai = [];
    private $redSoals = [];
    private $jadwalModel, $db, $jadwalData, $ujian_id, $redis, $trxRedis;
    public function __construct()
    {
        parent::__construct();
        $this->jadwalModel = new Jadwal();
    }
    public function index($jadwal_id)
    {
        $ujian_id = $this->request->getVar('id');
        if (is_string($ujian_id)) $ujian_id = [$ujian_id];
        $jadwalData = $this->jadwalModel->findId(base64_decode($jadwal_id));
        if (!$jadwalData) return $this->fail(['message' => "Jadwal tidak ditemukan"]);
        $this->db = db_connect();
        if (!$ujian_id) {
            $ujian_id = $this->db->table('ujian_siswa')->select('GROUP_CONCAT(id) ujian_id')->where('jadwal_id', $jadwalData['id'])->groupBy('jadwal_id')->get()->getRowArray();
            if (!$ujian_id) return $this->fail(['message' => "Tidak ada ujian yang dapat dibuat"]);
            $ujian_id = explode(',', $ujian_id['ujian_id']);
        }
        $this->ujian_id = $ujian_id;
        $this->jadwalData = $jadwalData;
        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");
            }
        }

        if (redison()) {
            $keyJawaban = [];
            foreach ($ujian_id as $uid) {
                foreach ($this->redis->keys("jawaban_pg_ujian_siswa-$uid-*") as $redS) {
                    $keyJawaban[] = $redS;
                    if (count($keyJawaban) >= 5000) {
                        $this->redis->del($keyJawaban);
                        $keyJawaban = [];
                    }
                }
                foreach ($this->redis->keys("jawaban_pgmulti_ujian_siswa-$uid-*") as $redS) {
                    $keyJawaban[] = $redS;
                    if (count($keyJawaban) >= 5000) {
                        $this->redis->del($keyJawaban);
                        $keyJawaban = [];
                    }
                }
                foreach ($this->redis->keys("jawaban_pgtf_ujian_siswa-$uid-*") as $redS) {
                    $keyJawaban[] = $redS;
                    if (count($keyJawaban) >= 5000) {
                        $this->redis->del($keyJawaban);
                        $keyJawaban = [];
                    }
                }
                foreach ($this->redis->keys("jawaban_pgcouple_ujian_siswa-$uid-*") as $redS) {
                    $keyJawaban[] = $redS;
                    if (count($keyJawaban) >= 5000) {
                        $this->redis->del($keyJawaban);
                        $keyJawaban = [];
                    }
                }
                foreach ($this->redis->keys("jawaban_shortentry_ujian_siswa-$uid-*") as $redS) {
                    $keyJawaban[] = $redS;
                    if (count($keyJawaban) >= 5000) {
                        $this->redis->del($keyJawaban);
                        $keyJawaban = [];
                    }
                }
                foreach ($this->redis->keys("jawaban_esai_ujian_siswa-$uid-*") as $redS) {
                    $keyJawaban[] = $redS;
                    if (count($keyJawaban) >= 5000) {
                        $this->redis->del($keyJawaban);
                        $keyJawaban = [];
                    }
                }
            }
            if ($keyJawaban) $this->redis->del($keyJawaban);
            $this->trxRedis = $this->redis->transaction();
        }
        $this->db->transStart();
        $soals = $this->db->table('soal_data sd');
        $soals->select('sd.*');
        $soals->join('draft_soal ds', 'ds.soal_id=sd.id');
        $soals->where(['ds.draft_id' => $jadwalData['draft_id']]);
        $soals = $soals->get()->getResultArray();
        if (count($soals) <= 0) return $this->fail(['message' => 'Belum ada soal di draft!']);
        foreach ($soals as $k => $v) {
            if ($v['jenis_soal'] == (new BankSoal())->jenis('pg')) $this->soal_pg[] = $v;
            elseif ($v['jenis_soal'] == (new BankSoal())->jenis('pgmulti')) $this->soal_pgmulti[] = $v;
            elseif ($v['jenis_soal'] == (new BankSoal())->jenis('pgtf')) $this->soal_pgtf[] = $v;
            elseif ($v['jenis_soal'] == (new BankSoal())->jenis('pgcouple')) $this->soal_pgcouple[] = $v;
            elseif ($v['jenis_soal'] == (new BankSoal())->jenis('esai')) $this->soal_esai[] = $v;
            elseif ($v['jenis_soal'] == (new BankSoal())->jenis('shortentry')) $this->soal_shortentry[] = $v;
        }
        $this->generate_pgcommon();
        // $this->db->table('jawaban_pg_ujian_siswa')->whereIn('ujian_id', $ujian_id)->delete();
        // if ($this->jawaban_pg) $this->db->table('jawaban_pg_ujian_siswa')->insertBatch($this->jawaban_pg);
        $this->generate_pgmulti();
        // $this->db->table('jawaban_pgmulti_ujian_siswa')->whereIn('ujian_id', $ujian_id)->delete();
        // if ($this->jawaban_pgmulti) $this->db->table('jawaban_pgmulti_ujian_siswa')->insertBatch($this->jawaban_pgmulti);
        $this->generate_pgtf();
        // $this->db->table('jawaban_pgtf_ujian_siswa')->whereIn('ujian_id', $ujian_id)->delete();
        // if ($this->jawaban_pgtf) $this->db->table('jawaban_pgtf_ujian_siswa')->insertBatch($this->jawaban_pgtf);
        $this->generate_pgcouple();
        // $this->db->table('jawaban_pgcouple_ujian_siswa')->whereIn('ujian_id', $ujian_id)->delete();
        // if ($this->jawaban_pgcouple) $this->db->table('jawaban_pgcouple_ujian_siswa')->insertBatch($this->jawaban_pgcouple);
        $this->generate_shortentry();
        // $this->db->table('jawaban_shortentry_ujian_siswa')->whereIn('ujian_id', $ujian_id)->delete();
        // if ($this->jawaban_shortentry) $this->db->table('jawaban_shortentry_ujian_siswa')->insertBatch($this->jawaban_shortentry);
        $this->generate_esai();
        // $this->db->table('jawaban_esai_ujian_siswa')->whereIn('ujian_id', $ujian_id)->delete();
        // if ($this->jawaban_esai) $this->db->table('jawaban_esai_ujian_siswa')->insertBatch($this->jawaban_esai);
        $this->db->table('ujian_siswa')->set([
            'status' => '0',
            'pg_benar' => 0,
            'pgtf_benar' => 0,
            'pgmulti_benar' => 0,
            'pgcouple_benar' => 0,
            'shortentry_benar' => 0,
            'total_pg' => 0,
            'total_shortentry' => 0,
            'nilai_pg' => 0,
            'nilai_esai' => 0,
            'ip_address' => null,
            'jwt' => null,
            'hasCheating' => '0',
            'soal_generated' => time(),
            'start_at' => null,
            'end_at' => null,
        ])->whereIn('id', $ujian_id)->update();
        $this->db->transComplete();
        if (redison()) $this->trxRedis->execute();
        if (redison()) $this->redis->disconnect();
        if ($this->db->transStatus() === FALSE) return $this->fail(['message' => "Gagal Generate Soal"]);
        setLog("Generate Soal Jadwal " . $jadwalData['nama']);
        return $this->respond(['message' => "Berhasil Generate Soal"]);
    }

    private function generate_pgcommon()
    {
        $this->db->table('jawaban_pg_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        $this->db->table('jawaban_pg_temp_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        foreach ($this->ujian_id as $uid) {
            if ($this->jadwalData['acak_soal'] == '1') shuffle($this->soal_pg);
            foreach ($this->soal_pg as $ks => $vs) {
                if ($ks >= $this->jadwalData['visible_pg']) break;
                $this->jawaban_pg[] = [
                    'ujian_id' => $uid,
                    'soal_id' => $vs['id'],
                    'opsi_id' => null,
                    'created_at' => time() + $ks,
                    'updated_at' => time() + $ks
                ];
                if (redison()) {
                    $this->trxRedis->set("soal-$vs[id]", json_encode([
                        'soal_id' => $vs['id'],
                        'jenis_soal' => $vs['jenis_soal'],
                        'question' => $vs['question'],
                    ]));
                    $this->trxRedis->set("jawaban_pg_ujian_siswa-$uid-$vs[id]", "");
                }
            }
        }
        if (!redison() && $this->jawaban_pg) $this->db->table('jawaban_pg_temp_ujian_siswa')->insertBatch($this->jawaban_pg);
    }
    private function generate_pgtf()
    {
        $this->db->table('jawaban_pgtf_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        $this->db->table('jawaban_pgtf_temp_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        foreach ($this->ujian_id as $uid) {
            if ($this->jadwalData['acak_soal'] == '1') shuffle($this->soal_pgtf);
            foreach ($this->soal_pgtf as $ks => $vs) {
                if ($ks >= $this->jadwalData['visible_pgtf']) break;
                $this->jawaban_pgtf[] = [
                    'ujian_id' => $uid,
                    'soal_id' => $vs['id'],
                    'opsi_id' => null,
                    'tf' => null,
                    'created_at' => time() + $ks
                ];
                if (redison()) {
                    $this->trxRedis->set("soal-$vs[id]", json_encode([
                        'soal_id' => $vs['id'],
                        'jenis_soal' => $vs['jenis_soal'],
                        'question' => $vs['question'],
                    ]));

                    $this->trxRedis->set("jawaban_pgtf_ujian_siswa-$uid-$vs[id]", "");
                }
            }
        }
        if (!redison() && $this->jawaban_pgtf) $this->db->table('jawaban_pgtf_temp_ujian_siswa')->insertBatch($this->jawaban_pgtf);
    }
    private function generate_pgmulti()
    {
        $this->db->table('jawaban_pgmulti_temp_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        $this->db->table('jawaban_pgmulti_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        foreach ($this->ujian_id as $uid) {
            if ($this->jadwalData['acak_soal'] == '1') shuffle($this->soal_pgmulti);
            foreach ($this->soal_pgmulti as $ks => $vs) {
                if ($ks >= $this->jadwalData['visible_pgmulti']) break;
                $this->jawaban_pgmulti[] = [
                    'ujian_id' => $uid,
                    'soal_id' => $vs['id'],
                    'opsi_id' => null,
                    'created_at' => time() + $ks,
                ];
                if (redison()) {
                    $this->trxRedis->set("soal-$vs[id]", json_encode([
                        'soal_id' => $vs['id'],
                        'jenis_soal' => $vs['jenis_soal'],
                        'question' => $vs['question'],
                    ]));

                    $this->trxRedis->set("jawaban_pgmulti_ujian_siswa-$uid-$vs[id]", "");
                }
            }
        }
        if (!redison() && $this->jawaban_pgmulti) $this->db->table('jawaban_pgmulti_temp_ujian_siswa')->insertBatch($this->jawaban_pgmulti);
    }
    private function generate_pgcouple()
    {
        $this->db->table('jawaban_pgcouple_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        $this->db->table('jawaban_pgcouple_temp_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        foreach ($this->ujian_id as $uid) {
            if ($this->jadwalData['acak_soal'] == '1') shuffle($this->soal_pgcouple);
            foreach ($this->soal_pgcouple as $ks => $vs) {
                if ($ks >= $this->jadwalData['visible_pgcouple']) break;
                $this->jawaban_pgcouple[] = [
                    'ujian_id' => $uid,
                    'soal_id' => $vs['id'],
                    'couple_id' => null,
                    'opsi_id' => null,
                    'created_at' => time() + $ks,
                ];
                if (redison()) {
                    $this->trxRedis->set("soal-$vs[id]", json_encode([
                        'soal_id' => $vs['id'],
                        'jenis_soal' => $vs['jenis_soal'],
                        'question' => $vs['question'],
                    ]));

                    $this->trxRedis->set("jawaban_pgcouple_ujian_siswa-$uid-$vs[id]", "");
                }
            }
        }
        if (!redison() && $this->jawaban_pgcouple) $this->db->table('jawaban_pgcouple_temp_ujian_siswa')->insertBatch($this->jawaban_pgcouple);
    }
    private function generate_shortentry()
    {
        $this->db->table('jawaban_shortentry_temp_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        $this->db->table('jawaban_shortentry_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        foreach ($this->ujian_id as $uid) {
            if ($this->jadwalData['acak_soal'] == '1') shuffle($this->soal_shortentry);
            foreach ($this->soal_shortentry as $ks => $vs) {
                if ($ks >= $this->jadwalData['visible_shortentry']) break;
                $this->jawaban_shortentry[] = [
                    'ujian_id' => $uid,
                    'soal_id' => $vs['id'],
                    'respond' => null,
                    'created_at' => time() + $ks,
                    'updated_at' => time() + $ks
                ];
                if (redison()) {
                    $this->trxRedis->set("soal-$vs[id]", json_encode([
                        'soal_id' => $vs['id'],
                        'jenis_soal' => $vs['jenis_soal'],
                        'question' => $vs['question'],
                    ]));

                    $this->trxRedis->set("jawaban_shortentry_ujian_siswa-$uid-$vs[id]", "");
                }
            }
        }
        if (!redison() && $this->jawaban_shortentry) $this->db->table('jawaban_shortentry_temp_ujian_siswa')->insertBatch($this->jawaban_shortentry);
    }
    private function generate_esai()
    {
        $this->db->table('jawaban_esai_temp_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        $this->db->table('jawaban_esai_ujian_siswa')->whereIn('ujian_id', $this->ujian_id)->delete();
        foreach ($this->ujian_id as $uid) {
            if ($this->jadwalData['acak_soal'] == '1') shuffle($this->soal_esai);
            foreach ($this->soal_esai as $ks => $vs) {
                if ($ks >= $this->jadwalData['visible_esai']) break;
                $this->jawaban_esai[] = [
                    'ujian_id' => $uid,
                    'soal_id' => $vs['id'],
                    'esai' => null,
                    'nilai' => 0,
                    'created_at' => time() + $ks,
                    'updated_at' => time() + $ks
                ];
                if (redison()) {
                    $this->trxRedis->set("soal-$vs[id]", json_encode([
                        'soal_id' => $vs['id'],
                        'jenis_soal' => $vs['jenis_soal'],
                        'question' => $vs['question'],
                    ]));

                    $this->trxRedis->set("jawaban_esai_ujian_siswa-$uid-$vs[id]", "");
                }
            }
        }
        if (!redison() && $this->jawaban_esai) $this->db->table('jawaban_esai_temp_ujian_siswa')->insertBatch($this->jawaban_esai);
    }
}
