<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Polling extends CI_Controller {

    public function __construct() {
        parent::__construct();
        $this->load->model('Polling_model', 'polling_model');
        $this->load->library(['session', 'form_validation']);
        $this->load->helper(['url', 'form']);

        // Pastikan user sudah login
        if (!$this->session->userdata('user_id')) {
            redirect('auth/login');
        }
    }

    // ─────────────────────────────────────────────────────────
    //  HELPER PRIVATE
    // ─────────────────────────────────────────────────────────

    private function _is_admin() {
        return $this->session->userdata('role') === 'admin';
    }

    /**
     * Load view dengan layout (header + sidebar + footer).
     * Sesuaikan nama view layout dengan proyek Anda.
     */
    private function _render($view, $data = []) {
        // Data global yang dibutuhkan sidebar
        $data['is_admin']           = $this->_is_admin();
        $data['count_polling_aktif'] = $this->polling_model->count_status('aktif');

        // Ambil unread pengaduan & saran jika dibutuhkan sidebar
        if ($this->_is_admin()) {
            if ($this->db->table_exists('pengaduan')) {
                $data['unread_pengaduan'] = $this->db
                    ->where('status', 'baru')
                    ->count_all_results('pengaduan');
            }
            if ($this->db->table_exists('saran')) {
                $data['unread_saran'] = $this->db
                    ->where('status', 'baru')
                    ->count_all_results('saran');
            }
        }

        $this->load->view('templates/header', $data);
        $this->load->view($view, $data);
        $this->load->view('templates/footer', $data);
    }

    // ─────────────────────────────────────────────────────────
    //  INDEX — Daftar semua polling
    // ─────────────────────────────────────────────────────────

    public function index() {
        $status  = $this->input->get('status'); // aktif | selesai | ditutup | null
        $polling = $this->polling_model->get_all($status);

        $user_id = $this->session->userdata('user_id');

        // Untuk warga: tandai sudah/belum vote & siapkan preview opsi
        if (!$this->_is_admin()) {
            foreach ($polling as &$p) {
                $vote          = $this->polling_model->get_user_vote($p->id, $user_id);
                $p->sudah_vote  = !empty($vote);
                $p->opsi_preview = $p->opsi_json; // mini bar pakai opsi_json langsung
            }
            unset($p);
        } else {
            // Admin: tampilkan mini preview juga
            foreach ($polling as &$p) {
                $p->opsi_preview = $p->opsi_json;
                $opsi_arr        = json_decode($p->opsi_json, true) ?? [];
                $p->total_suara  = array_sum(array_column($opsi_arr, 'suara'));
            }
            unset($p);
        }

        $data = [
            'polling'     => $polling,
            'count_aktif' => $this->polling_model->count_status('aktif'),
            'title'       => 'Polling Warga',
        ];

        $this->_render('polling/index', $data);
    }

    // ─────────────────────────────────────────────────────────
    //  TAMBAH — Form buat polling baru
    // ─────────────────────────────────────────────────────────

    public function tambah() {
        if (!$this->_is_admin()) {
            show_error('Akses ditolak. Hanya admin yang dapat membuat polling.', 403);
        }

        $data = [
            'edit_mode' => false,
            'title'     => 'Buat Polling Baru',
        ];

        $this->_render('polling/tambah', $data);
    }

    // ─────────────────────────────────────────────────────────
    //  SIMPAN — Proses POST tambah polling
    // ─────────────────────────────────────────────────────────

    public function simpan() {
        if (!$this->_is_admin()) {
            show_error('Akses ditolak.', 403);
        }

        $this->form_validation->set_rules('judul',        'Judul',        'required|trim|max_length[255]');
        $this->form_validation->set_rules('tanggal_mulai','Tanggal Mulai','required');
        $this->form_validation->set_rules('opsi_json',    'Opsi Jawaban', 'required');

        if (!$this->form_validation->run()) {
            // Kembalikan ke form dengan error
            $data = ['edit_mode' => false, 'title' => 'Buat Polling Baru'];
            $this->_render('polling/tambah', $data);
            return;
        }

        // Validasi opsi JSON
        $opsi_raw = $this->input->post('opsi_json');
        $opsi     = json_decode($opsi_raw, true);

        if (empty($opsi) || !is_array($opsi) || count($opsi) < 2) {
            $this->session->set_flashdata('error', 'Minimal 2 opsi jawaban harus diisi.');
            redirect('polling/tambah');
            return;
        }

        // Bersihkan opsi — pastikan setiap item punya teks & suara = 0
        $opsi_bersih = [];
        foreach ($opsi as $op) {
            $teks = trim($op['teks'] ?? '');
            if ($teks !== '') {
                $opsi_bersih[] = ['teks' => $teks, 'suara' => 0];
            }
        }

        if (count($opsi_bersih) < 2) {
            $this->session->set_flashdata('error', 'Minimal 2 opsi jawaban tidak boleh kosong.');
            redirect('polling/tambah');
            return;
        }

        // Validasi tanggal selesai > tanggal mulai
        $tgl_mulai   = $this->input->post('tanggal_mulai');
        $tgl_selesai = $this->input->post('tanggal_selesai') ?: null;
        if ($tgl_selesai && $tgl_selesai < $tgl_mulai) {
            $this->session->set_flashdata('error', 'Tanggal selesai tidak boleh sebelum tanggal mulai.');
            redirect('polling/tambah');
            return;
        }

        $insert = [
            'judul'           => $this->input->post('judul', true),
            'deskripsi'       => $this->input->post('deskripsi', true),
            'opsi_json'       => json_encode($opsi_bersih, JSON_UNESCAPED_UNICODE),
            'tanggal_mulai'   => $tgl_mulai,
            'tanggal_selesai' => $tgl_selesai,
            'hasil_realtime'  => $this->input->post('hasil_realtime') ? 1 : 0,
            'izin_ganti'      => $this->input->post('izin_ganti')     ? 1 : 0,
            'anonim'          => $this->input->post('anonim')          ? 1 : 0,
            'status'          => 'aktif',
            'dibuat_oleh'     => $this->session->userdata('user_id'),
        ];

        $this->polling_model->insert($insert);
        $this->session->set_flashdata('success', 'Polling berhasil dibuat dan sudah aktif!');
        redirect('polling');
    }

    // ─────────────────────────────────────────────────────────
    //  DETAIL — Tampilkan detail + form vote
    // ─────────────────────────────────────────────────────────

    public function detail($id = null) {
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $user_id  = $this->session->userdata('user_id');
        $is_admin = $this->_is_admin();

        $vote   = $this->polling_model->get_user_vote($id, $user_id);
        $voters = ($is_admin && !$item->anonim)
                ? $this->polling_model->get_voters($id)
                : [];

        // Hitung total suara dari opsi_json
        $opsi_arr    = json_decode($item->opsi_json, true) ?? [];
        $total_suara = array_sum(array_column($opsi_arr, 'suara'));

        $data = [
            'item'               => $item,
            'sudah_vote'         => !empty($vote),
            'pilihan_sebelumnya' => $vote->pilihan ?? null,
            'voters'             => $voters,
            'total_suara'        => $total_suara,
            'title'              => 'Detail Polling',
        ];

        $this->_render('polling/detail', $data);
    }

    // ─────────────────────────────────────────────────────────
    //  VOTE — Proses POST suara warga
    // ─────────────────────────────────────────────────────────

    public function vote($id = null) {
        if (!$id) redirect('polling');

        // Hanya warga yang bisa vote (admin tidak ikut polling)
        if ($this->_is_admin()) {
            $this->session->set_flashdata('error', 'Admin tidak dapat ikut voting.');
            redirect('polling/detail/' . $id);
            return;
        }

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        if ($item->status !== 'aktif') {
            $this->session->set_flashdata('error', 'Polling ini sudah tidak aktif.');
            redirect('polling/detail/' . $id);
            return;
        }

        $pilihan = $this->input->post('pilihan', true);
        if (empty($pilihan)) {
            $this->session->set_flashdata('error', 'Silakan pilih salah satu opsi terlebih dahulu.');
            redirect('polling/detail/' . $id);
            return;
        }

        $user_id = $this->session->userdata('user_id');
        $vote    = $this->polling_model->get_user_vote($id, $user_id);

        // Cek apakah boleh ganti suara
        if ($vote && !$item->izin_ganti) {
            $this->session->set_flashdata('error', 'Anda sudah memberikan suara dan tidak dapat mengubahnya.');
            redirect('polling/detail/' . $id);
            return;
        }

        // Validasi pilihan ada di opsi yang valid
        $opsi_arr = json_decode($item->opsi_json, true) ?? [];
        $pilihan_valid = array_column($opsi_arr, 'teks');
        if (!in_array($pilihan, $pilihan_valid)) {
            $this->session->set_flashdata('error', 'Pilihan tidak valid.');
            redirect('polling/detail/' . $id);
            return;
        }

        // Mulai transaksi database
        $this->db->trans_start();

        // Kurangi suara lama jika sedang ganti pilihan
        if ($vote) {
            foreach ($opsi_arr as &$op) {
                if ($op['teks'] === $vote->pilihan && $op['suara'] > 0) {
                    $op['suara']--;
                    break;
                }
            }
            unset($op);
        }

        // Tambah suara untuk pilihan baru
        foreach ($opsi_arr as &$op) {
            if ($op['teks'] === $pilihan) {
                $op['suara']++;
                break;
            }
        }
        unset($op);

        // Simpan opsi_json yang sudah diupdate
        $this->polling_model->update_opsi($id, json_encode($opsi_arr, JSON_UNESCAPED_UNICODE));

        // Upsert record vote warga
        $nama = $this->session->userdata('nama') ?: 'Warga';
        if ($vote) {
            $this->polling_model->update_vote($vote->id, $pilihan);
        } else {
            $this->polling_model->insert_vote([
                'polling_id' => (int)$id,
                'user_id'    => (int)$user_id,
                'nama'       => $nama,
                'pilihan'    => $pilihan,
            ]);
        }

        $this->db->trans_complete();

        if ($this->db->trans_status() === false) {
            $this->session->set_flashdata('error', 'Terjadi kesalahan, suara gagal disimpan. Silakan coba lagi.');
        } else {
            $msg = $vote
                ? 'Pilihan Anda berhasil diubah. Terima kasih!'
                : 'Suara Anda berhasil diberikan. Terima kasih atas partisipasi Anda!';
            $this->session->set_flashdata('success', $msg);
        }

        redirect('polling/detail/' . $id);
    }

    // ─────────────────────────────────────────────────────────
    //  EDIT — Form edit polling
    // ─────────────────────────────────────────────────────────

    public function edit($id = null) {
        if (!$this->_is_admin()) {
            show_error('Akses ditolak.', 403);
        }
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $data = [
            'edit_mode' => true,
            'item'      => $item,
            'title'     => 'Edit Polling',
        ];

        $this->_render('polling/tambah', $data);
    }

    // ─────────────────────────────────────────────────────────
    //  UPDATE — Proses POST edit polling
    // ─────────────────────────────────────────────────────────

    public function update($id = null) {
        if (!$this->_is_admin()) show_error('Akses ditolak.', 403);
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $this->form_validation->set_rules('judul',        'Judul',        'required|trim|max_length[255]');
        $this->form_validation->set_rules('tanggal_mulai','Tanggal Mulai','required');

        if (!$this->form_validation->run()) {
            $data = ['edit_mode' => true, 'item' => $item, 'title' => 'Edit Polling'];
            $this->_render('polling/tambah', $data);
            return;
        }

        $tgl_mulai   = $this->input->post('tanggal_mulai');
        $tgl_selesai = $this->input->post('tanggal_selesai') ?: null;

        $update = [
            'judul'           => $this->input->post('judul', true),
            'deskripsi'       => $this->input->post('deskripsi', true),
            'tanggal_mulai'   => $tgl_mulai,
            'tanggal_selesai' => $tgl_selesai,
            'hasil_realtime'  => $this->input->post('hasil_realtime') ? 1 : 0,
            'izin_ganti'      => $this->input->post('izin_ganti')     ? 1 : 0,
            'anonim'          => $this->input->post('anonim')          ? 1 : 0,
        ];

        // Update opsi hanya jika ada kiriman dari form
        $opsi_raw = $this->input->post('opsi_json');
        if (!empty($opsi_raw)) {
            $opsi = json_decode($opsi_raw, true);
            if (is_array($opsi) && count($opsi) >= 2) {
                // Pertahankan jumlah suara lama dari opsi yang sama
                $opsi_lama = json_decode($item->opsi_json, true) ?? [];
                $suara_map = [];
                foreach ($opsi_lama as $ol) {
                    $suara_map[$ol['teks']] = $ol['suara'];
                }

                $opsi_baru = [];
                foreach ($opsi as $op) {
                    $teks = trim($op['teks'] ?? '');
                    if ($teks !== '') {
                        $opsi_baru[] = [
                            'teks'  => $teks,
                            'suara' => $suara_map[$teks] ?? 0, // pertahankan suara lama
                        ];
                    }
                }

                if (count($opsi_baru) >= 2) {
                    $update['opsi_json'] = json_encode($opsi_baru, JSON_UNESCAPED_UNICODE);
                }
            }
        }

        $this->polling_model->update($id, $update);
        $this->session->set_flashdata('success', 'Polling berhasil diperbarui!');
        redirect('polling');
    }

    // ─────────────────────────────────────────────────────────
    //  TUTUP — Ubah status menjadi 'ditutup'
    // ─────────────────────────────────────────────────────────

    public function tutup($id = null) {
        if (!$this->_is_admin()) show_error('Akses ditolak.', 403);
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        if ($item->status !== 'aktif') {
            $this->session->set_flashdata('error', 'Polling ini tidak sedang aktif.');
            redirect('polling');
            return;
        }

        $this->polling_model->update($id, ['status' => 'ditutup']);
        $this->session->set_flashdata('success', 'Polling "' . $item->judul . '" telah ditutup.');
        redirect('polling');
    }

    // ─────────────────────────────────────────────────────────
    //  SELESAI — Ubah status menjadi 'selesai'
    // ─────────────────────────────────────────────────────────

    public function selesai($id = null) {
        if (!$this->_is_admin()) show_error('Akses ditolak.', 403);
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $this->polling_model->update($id, ['status' => 'selesai']);
        $this->session->set_flashdata('success', 'Polling "' . $item->judul . '" ditandai selesai.');
        redirect('polling');
    }

    // ─────────────────────────────────────────────────────────
    //  AKTIFKAN — Ubah status kembali menjadi 'aktif'
    // ─────────────────────────────────────────────────────────

    public function aktifkan($id = null) {
        if (!$this->_is_admin()) show_error('Akses ditolak.', 403);
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $this->polling_model->update($id, ['status' => 'aktif']);
        $this->session->set_flashdata('success', 'Polling "' . $item->judul . '" kembali diaktifkan.');
        redirect('polling');
    }

    // ─────────────────────────────────────────────────────────
    //  HAPUS — Hapus polling beserta semua votes-nya
    // ─────────────────────────────────────────────────────────

    public function hapus($id = null) {
        if (!$this->_is_admin()) show_error('Akses ditolak.', 403);
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $judul = $item->judul;
        $this->polling_model->delete($id); // cascade delete votes via FK atau manual di model

        $this->session->set_flashdata('success', 'Polling "' . $judul . '" berhasil dihapus.');
        redirect('polling');
    }

    // ─────────────────────────────────────────────────────────
    //  RESET VOTES — Hapus semua suara (admin only)
    // ─────────────────────────────────────────────────────────

    public function reset_votes($id = null) {
        if (!$this->_is_admin()) show_error('Akses ditolak.', 403);
        if (!$id) redirect('polling');

        $item = $this->polling_model->get_by_id($id);
        if (!$item) show_404();

        $this->db->trans_start();

        // Reset semua suara di opsi_json menjadi 0
        $opsi_arr = json_decode($item->opsi_json, true) ?? [];
        foreach ($opsi_arr as &$op) {
            $op['suara'] = 0;
        }
        unset($op);
        $this->polling_model->update_opsi($id, json_encode($opsi_arr, JSON_UNESCAPED_UNICODE));

        // Hapus semua record vote
        $this->db->where('polling_id', $id)->delete('polling_votes');

        $this->db->trans_complete();

        $this->session->set_flashdata('success', 'Semua suara polling berhasil direset.');
        redirect('polling/detail/' . $id);
    }

}