<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use App\Models\HasilUjianModel;
use App\Models\SoalModel;
use App\Models\PesertaModel;
use App\Models\SoalOpsiModel;
use App\Models\JawabanModel;
use App\Models\UjianModel;
use App\Models\TopikSoalModel;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use CodeIgniter\HTTP\ResponseInterface;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class HasilUjianController extends BaseController
{
    protected $hasilUjianModel;
    protected $soalModel;
    protected $soalOpsiModel;
    protected $jawabanModel;
    protected $pesertaModel;
    protected $validation;
    protected $ujianModel;
    protected $topikSoalModel;
    public function __construct()
    {
        $this->soalModel = new SoalModel();
        $this->pesertaModel = new PesertaModel();
        $this->soalOpsiModel = new SoalOpsiModel();
        $this->ujianModel = new UjianModel();
        $this->hasilUjianModel = new HasilUjianModel();
        $this->jawabanModel = new JawabanModel();
        $this->topikSoalModel = new TopikSoalModel();
        $this->validation = \Config\Services::validation();
    }

    public function index($idujian)
    {
        $ujian = $this->ujianModel->find($idujian);

        $data = [
            'title' => 'Data Hasil Ujian',
            'ujianid' => $idujian,
            'setting' => $this->appSetting(),
            'ujian' => $ujian
        ];

        return view('Panel/Hasil/hasil_ujian_view', $data);
    }

    public function getAll($ujianId = null)
    {
        if (!$this->request->isAJAX()) {
            return $this->fail('Hanya bisa diakses via AJAX.');
        }

        if (!$ujianId) {
            return $this->response->setJSON([
                'status' => false,
                'message' => 'ID Ujian tidak ditemukan.'
            ]);
        }

        $hasil = $this->hasilUjianModel->getHasilUjianLengkap($ujianId);

        return $this->response->setJSON([
            'status' => true,
            'data'   => $hasil,
        ]);
    }
    public function ulangUjian($id)
    {
        if ($this->request->isAJAX()) {
            // Ambil data hasil ujian terlebih dahulu
            $hasil = $this->hasilUjianModel->find($id);

            if (!$hasil) {
                return $this->response->setJSON([
                    'status' => false,
                    'message' => 'Data hasil ujian tidak ditemukan.'
                ]);
            }

            // Reset status ujian
            $this->hasilUjianModel->resetUjian($id);

            // Hapus jawaban berdasarkan ujian_id dan peserta_id dari hasil ujian
            $this->jawabanModel
                ->where('ujian_id', $hasil['ujian_id'])
                ->where('peserta_id', $hasil['peserta_id'])
                ->delete();

            return $this->response->setJSON([
                'status' => true,
                'message' => 'Ujian berhasil diulang dan jawaban dihapus.'
            ]);
        }

        return $this->fail('Akses tidak valid.');
    }


    public function selesaikanUjian($id)
    {
        if ($this->request->isAJAX()) {
            $model = new HasilUjianModel();
            $model->tandaiSelesai($id);

            return $this->response->setJSON([
                'status' => true,
                'message' => 'Ujian ditandai sebagai selesai.'
            ]);
        }

        return $this->fail('Akses tidak valid.');
    }
    private function fail($message)
    {
        return $this->response->setJSON([
            'status' => false,
            'message' => $message
        ]);
    }

    public function jawaban($hasilUjianId)
    {
        $hasil = $this->hasilUjianModel->find($hasilUjianId);
        if (!$hasil) {
            return $this->response->setJSON([
                'status' => false,
                'message' => 'Data hasil ujian tidak ditemukan.'
            ]);
        }

        $ujian = $this->ujianModel->find($hasil['ujian_id']);
        if (!$ujian) {
            return $this->response->setJSON([
                'status' => false,
                'message' => 'Data ujian tidak ditemukan.'
            ]);
        }

        $peserta = $this->pesertaModel
            ->select('peserta.nama, peserta.nisn, kelas.nama AS nama_kelas')
            ->join('kelas', 'kelas.id = peserta.kelas_id', 'left')
            ->find($hasil['peserta_id']);

        $soalList = $this->soalModel
            ->select('id, soal_no, pertanyaan, jenis_soal')
            ->where('bank_soal_id', $ujian['bank_soal_id'])
            ->orderBy('soal_no', 'ASC')
            ->findAll();

        $soalIds = array_column($soalList, 'id');
        $opsiList = [];

        if (!empty($soalIds)) {
            $allOpsi = $this->soalOpsiModel
                ->select('id, soal_id, label, teks, is_true, pasangan, bobot')
                ->whereIn('soal_id', $soalIds)
                ->orderBy('label', 'ASC')
                ->findAll();

            foreach ($soalIds as $soalId) {
                $opsiList[$soalId] = array_values(array_filter($allOpsi, fn($op) => $op['soal_id'] === $soalId));
            }
        }

        return $this->response->setJSON([
            'status' => true,
            'data' => [
                'peserta'   => $peserta,
                'jawaban'   => json_decode($hasil['jawaban_json'], true) ?? [],
                'soalList'  => $soalList,
                'opsiList'  => $opsiList,
                'hasil' => $hasil
            ]
        ]);
    }

    public function exportSkoring($ujianId)
    {
        $hasilList = $this->hasilUjianModel->getSkoringByUjianId($ujianId);
        if (!$hasilList) {
            return redirect()->back()->with('error', 'Data hasil ujian tidak ditemukan.');
        }

        $ujian = $this->ujianModel->getWithNamaMapel($ujianId);
        $soalList = $this->soalModel
            ->where('bank_soal_id', $ujian['bank_soal_id'])
            ->orderBy('soal_no', 'ASC')
            ->findAll();

        $topikList = $this->topikSoalModel
            ->whereIn('id', array_unique(array_column($soalList, 'topik_soal_id')))
            ->findAll();
        $topikMap = array_column($topikList, null, 'id');

        $daftarSoal = array_column($soalList, null, 'id');

        $spreadsheet = new Spreadsheet();

        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Skoring');
        // Judul besar
        $sheet->mergeCells('A1:M1');
        $sheet->setCellValue('A1', 'Hasil ' . $ujian['nama_ujian'] . ' - ' . $ujian['nama_mapel']);
        $sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
        $sheet->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
        // Header kolom
        $header = [
            'No',
            'NISN',
            'Nama',
            'Kelas',
            'Nilai PG',
            'Nilai Esai',
            'Nilai Total',
            'Poin Benar',
            'Poin Salah',
            'Poin Maksimal',
            'Lama Ujian',
            'Waktu Mulai',
            'Waktu Selesai'
        ];

        // Baris header ke-3
        foreach ($header as $i => $h) {
            $col = $this->colIndexToLetter($i);
            $sheet->setCellValue("{$col}3", $h);
        }

        // Header Soal Soal-1, Soal-2, ...
        $startColIndex = count($header);
        foreach ($soalList as $i => $soal) {
            $col = $this->colIndexToLetter($startColIndex + $i);
            $sheet->setCellValue("{$col}3", "Soal-" . ($i + 1));
        }

        $colCount = $startColIndex + count($soalList);
        for ($i = 0; $i < $colCount; $i++) {
            $colLetter = $this->colIndexToLetter($i);
            $sheet->getColumnDimension($colLetter)->setAutoSize(true);
        }
        // Styling header
        $lastCol = $this->colIndexToLetter($startColIndex + count($soalList) - 1);
        $sheet->getStyle("A3:{$lastCol}3")->getFont()->setBold(true);
        $sheet->getStyle("A3:{$lastCol}3")->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB('FFD9E1F2');
        $sheet->getStyle("A3:{$lastCol}3")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
        $sheet->freezePane('E4'); // Freeze sampai kolom "Nama"

        // Data mulai dari baris 4
        $row = 4;
        $no = 1;
        foreach ($hasilList as $hasil) {
            $lama = strtotime($hasil['waktu_selesai']) - strtotime($hasil['waktu_mulai']);
            $lamaFormat = gmdate("H:i:s", $lama);

            $jawaban = json_decode($hasil['jawaban_json'], true);

            $data = [
                $no++,
                $hasil['nisn'],
                $hasil['nama_peserta'],
                $hasil['nama_kelas'],
                $hasil['nilai_pg'] ?? 0,
                $hasil['nilai_esai'] ?? 0,
                $hasil['nilai_total'],
                $hasil['poin_benar'],
                $hasil['poin_salah'],
                $hasil['poin_maksimal'],
                $lamaFormat,
                $hasil['waktu_mulai'],
                $hasil['waktu_selesai'],
            ];

            // Data utama
            foreach ($data as $i => $val) {
                $col = $this->colIndexToLetter($i);
                $sheet->setCellValue("{$col}{$row}", $val);
            }

            // Data jawaban per soal
            foreach ($soalList as $i => $soal) {
                $col = $this->colIndexToLetter($startColIndex + $i);
                $jawabData = $jawaban[$soal['id']] ?? null;
                if (!$jawabData) {
                    $jawab = '-';
                } elseif (isset($jawabData['value'])) {
                    $jawab = $jawabData['value'];
                } elseif (isset($jawabData['text'])) {
                    $jawab = $jawabData['text'];
                } elseif (isset($jawabData['values'])) {
                    $jawab = implode(', ', $jawabData['values']);
                } elseif (is_array($jawabData)) {
                    $entries = [];
                    foreach ($jawabData as $k => $v) {
                        if (in_array($k, ['is_benar', 'poin'])) continue;
                        $entries[] = "$k: $v";
                    }
                    $jawab = implode(' | ', $entries);
                } else {
                    $jawab = '-';
                }
                $sheet->setCellValue("{$col}{$row}", $jawab);

                // Warnai jika jawaban ada dan ada nilai is_benar
                if (isset($jawabData['is_benar'])) {
                    $fillColor = $jawabData['is_benar'] ? 'C6EFCE' : 'F8CBAD'; // hijau atau merah muda
                    $sheet->getStyle("{$col}{$row}")->getFill()
                        ->setFillType(Fill::FILL_SOLID)
                        ->getStartColor()->setRGB($fillColor);
                }
            }

            $row++;
        }

        // Auto size kolom
        for ($i = 0; $i < $startColIndex + count($soalList); $i++) {
            $col = $this->colIndexToLetter($i);
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        // Border semua data
        $sheet->getStyle("A3:{$lastCol}" . ($row - 1))
            ->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);


        // Sheet 2: Analisis
        // Sheet 2: Analisis
        $sheet2 = $spreadsheet->createSheet();
        $sheet2->setTitle('Analisis');

        // Judul
        $sheet2->setCellValue('A1', 'Analisis ' . $ujian['nama_ujian'] . ' - ' . $ujian['nama_mapel']);

        // Header kolom awal
        $sheet2->setCellValue('A2', 'No');
        $sheet2->mergeCells('A2:A3');
        $sheet2->setCellValue('B2', 'Nama');
        $sheet2->mergeCells('B2:B3');
        $sheet2->setCellValue('C2', 'Kelas');
        $sheet2->mergeCells('C2:C3');
        $sheet2->freezePane('D4'); // Freeze sampai kolom "Nama"
        // Kolom topik
        $startCol = 2;
        foreach ($topikList as $i => $topik) {
            $colBase = $startCol + $i * 3 + 1;
            $colLetterStart = $this->colIndexToLetter($colBase);
            $colLetterEnd = $this->colIndexToLetter($colBase + 2);

            // Judul topik
            $sheet2->mergeCells("{$colLetterStart}2:{$colLetterEnd}2");
            $sheet2->setCellValue("{$colLetterStart}2", $topik['nama']);

            // Sub-kolom
            $sheet2->setCellValue("{$colLetterStart}3", 'Benar');
            $sheet2->setCellValue($this->colIndexToLetter($colBase + 1) . '3', 'Maks');
            $sheet2->setCellValue($this->colIndexToLetter($colBase + 2) . '3', 'Skor');
        }

        // Kolom Analisis Total
        $analisisStartCol = $startCol + count($topikList) * 3 + 1;
        $sheet2->mergeCells($this->colIndexToLetter($analisisStartCol) . '2:' . $this->colIndexToLetter($analisisStartCol + 2) . '2');
        $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol) . '2', 'Analisis');

        $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol) . '3', 'Total Benar');
        $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol + 1) . '3', 'Total Maks');
        $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol + 2) . '3', 'Skor');

        // Kolom Catatan
        $catatanCol = $analisisStartCol + 3;
        $sheet2->mergeCells($this->colIndexToLetter($catatanCol) . '2:' . $this->colIndexToLetter($catatanCol) . '3');
        $sheet2->setCellValue($this->colIndexToLetter($catatanCol) . '2', 'Catatan');

        // Data mulai baris 4
        $row = 4;
        $no = 1;
        foreach ($hasilList as $hasil) {
            $jawaban = json_decode($hasil['jawaban_json'], true);
            $sheet2->setCellValue("A{$row}", $no++);
            $sheet2->setCellValue("B{$row}", $hasil['nama_peserta']);
            $sheet2->setCellValue("C{$row}", $hasil['nama_kelas']);

            $catatanList = [];
            $totalBenar = 0;
            $totalMaks = 0;

            foreach ($topikList as $i => $topik) {
                $benar = 0;
                $maks = 0;
                foreach ($soalList as $soal) {
                    if ($soal['topik_soal_id'] != $topik['id']) continue;
                    $sId = $soal['id'];
                    $jawab = $jawaban[$sId] ?? [];
                    $benar += (int) ($jawab['poin'] ?? 0);
                    $maks += (int) ($soal['bobot'] ?? 1);
                }

                $skor = $maks > 0 ? round(($benar / $maks) * 100) : 0;

                // Tulis ke sheet
                $colBase = $startCol + $i * 3 + 1;
                $sheet2->setCellValue($this->colIndexToLetter($colBase) . $row, $benar);
                $sheet2->setCellValue($this->colIndexToLetter($colBase + 1) . $row, $maks);
                $sheet2->setCellValue($this->colIndexToLetter($colBase + 2) . $row, $skor);

                // Tambah ke catatan
                if ($maks > 0) {
                    if ($skor >= 80) {
                        $catatanList[] = 'sangat baik di topik ' . $topik['nama'];
                    } elseif ($skor >= 60) {
                        $catatanList[] = 'cukup di topik ' . $topik['nama'];
                    } else {
                        $catatanList[] = 'kurang di topik ' . $topik['nama'];
                    }
                }

                $totalBenar += $benar;
                $totalMaks += $maks;
            }

            // Total analisis
            $skorTotal = $totalMaks > 0 ? round(($totalBenar / $totalMaks) * 100) : 0;
            $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol) . $row, $totalBenar);
            $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol + 1) . $row, $totalMaks);
            $sheet2->setCellValue($this->colIndexToLetter($analisisStartCol + 2) . $row, $skorTotal);

            // Catatan deskriptif
            $sheet2->setCellValue($this->colIndexToLetter($catatanCol) . $row, implode(', ', $catatanList));

            $row++;
        }

        // === Styling Sheet Analisis ===

        // Judul besar
        $sheet2->mergeCells("A1:" . $this->colIndexToLetter($catatanCol) . "1");
        $sheet2->getStyle('A1')->getFont()->setBold(true)->setSize(14);
        $sheet2->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);

        // Header (baris 2-3)
        $headerEndCol = $this->colIndexToLetter($catatanCol);
        $sheet2->getStyle("A2:{$headerEndCol}3")->getFont()->setBold(true);
        $sheet2->getStyle("A2:{$headerEndCol}3")->getFill()
            ->setFillType(Fill::FILL_SOLID)
            ->getStartColor()->setRGB('DDEBF7');
        $sheet2->getStyle("A2:{$headerEndCol}3")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);

        // Autosize semua kolom
        for ($i = 0; $i <= $catatanCol; $i++) {
            $col = $this->colIndexToLetter($i);
            $sheet2->getColumnDimension($col)->setAutoSize(true);
        }

        // Border seluruh isi tabel
        $sheet2->getStyle("A2:{$headerEndCol}" . ($row - 1))
            ->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);

        // === Pewarnaan Skor ===
        for ($r = 4; $r < $row; $r++) {
            foreach ($topikList as $i => $topik) {
                $colSkor = $this->colIndexToLetter($startCol + $i * 3 + 3); // kolom Skor
                $cell = $colSkor . $r;
                $val = (int) $sheet2->getCell($cell)->getValue();
                $color = 'FFFFFF'; // default putih

                if ($val >= 80) {
                    $color = 'C6EFCE'; // hijau muda
                } elseif ($val >= 60) {
                    $color = 'FFF2CC'; // kuning
                } else {
                    $color = 'F8CBAD'; // merah muda
                }

                $sheet2->getStyle($cell)->getFill()
                    ->setFillType(Fill::FILL_SOLID)
                    ->getStartColor()->setRGB($color);
            }

            // Pewarnaan total skor
            $cellTotal = $this->colIndexToLetter($analisisStartCol + 2) . $r;
            $valTotal = (int) $sheet2->getCell($cellTotal)->getValue();
            $color = 'FFFFFF';
            if ($valTotal >= 80) {
                $color = 'C6EFCE';
            } elseif ($valTotal >= 60) {
                $color = 'FFF2CC';
            } else {
                $color = 'F8CBAD';
            }
            $sheet2->getStyle($cellTotal)->getFill()
                ->setFillType(Fill::FILL_SOLID)
                ->getStartColor()->setRGB($color);
        }


        // Download
        $fileName = 'Skoring_' . url_title($ujian['nama_ujian'], '_', true) . '.xlsx';
        $writer = new Xlsx($spreadsheet);
        $tempFile = tempnam(sys_get_temp_dir(), 'excel');
        $writer->save($tempFile);

        return $this->response
            ->download($fileName, file_get_contents($tempFile))
            ->setContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    }

    function colIndexToLetter($index)
    {
        $letters = '';
        while ($index >= 0) {
            $letters = chr($index % 26 + 65) . $letters;
            $index = floor($index / 26) - 1;
        }
        return $letters;
    }
}
