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

class Coi_disclosure extends AdminController
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('coi_disclosure_model');
        $this->load->helper('coi_disclosure/coi_disclosure');
    }

    private function _deny()
    {
        access_denied('coi_disclosure');
    }

    /** 15 questions (match your HTML) */
   private function questions()
{
    return [
        [
            'text' => 'Do you or any Connected Parties provide goods, services, or property to INCEIF?',
            'placeholder' => "Provide entity name, role, and confirm the date/reference of the PCEO’s written approval.",
        ],
        [
            'text' => 'Do you or any Connected Parties hold equity or financial interest in entities doing business with INCEIF?',
            'placeholder' => "Provide entity name, nature of interest, and confirm the date of the prior written approval from the PCEO is received",
        ],
        [
            'text' => 'Do your Connected Parties have business dealings with INCEIF contractors or suppliers?',
            'placeholder' => "Describe the relationship and confirm the date this interest was disclosed and approved by the PCEO.",
        ],
        [
            'text' => 'Have you received any gifts, hospitality, or benefits exceeding of substantial value (> RM200) or that could be perceived as lavish or influential?',
            'placeholder' => "Confirm the date you submitted the Gift, Hospitality and Entertainment Disclosure form and the status of the approval for this specific event.",
        ],
        [
            'text' => 'Were you involved in any hiring, supervision, assessment, or decision-making involving a Family member or Connected Party?',
            'placeholder' => "Describe the relationship and confirm the alternative oversight arrangements that were formally approved for this period.",
        ],
        [
            'text' => 'Are you engaged in any external employment, consultancy, or non-executive directorship',
            'placeholder' => "Confirm that an External Engagement Form was approved prior to commencing the activity and remains valid.",
        ],
        [
            'text' => 'Did you conduct public training, consulting, or speaking engagements for competitor institutions?',
            'placeholder' => "Confirm that an External Engagement Form was approved prior to commencing the activity and remains valid.",
        ],
        [
            'text' => 'Are you aware of any other events, transactions, arrangements or other situations that have occurred or may occur in the future that may cause conflict of interest?',
            'placeholder' => "Describe the situation and confirm any mitigation steps previously agreed upon with HC or the PCEO.",
        ],
    ];
}

    public function index()
    {
        if (staff_cant('view', 'coi_disclosure') && staff_cant('view_own', 'coi_disclosure')) {
            return $this->_deny();
        }
        $data['title'] = _l('coi_disclosure');
        $this->load->view('coi_disclosure/manage', $data);
    }

    public function table()
    {
        if (staff_cant('view', 'coi_disclosure') && staff_cant('view_own', 'coi_disclosure')) {
            return $this->_deny();
        }
        $this->app->get_table_data(module_views_path('coi_disclosure', 'tables/coi'));
    }

    public function create()
    {
        if (!staff_can('create', 'coi_disclosure')) return $this->_deny();

        
        $this->load->model('departments_model');  
    $staff_id = (int)get_staff_user_id();      
    $staff_depts = $this->departments_model->get_staff_departments($staff_id); // usually returns departmentid list
    $all_depts   = $this->departments_model->get(); // all departments with name

    // map id => name
    $map = [];
    foreach ((array)$all_depts as $d) {
        $map[(int)$d['departmentid']] = $d['name'];
    }

    // build display text: "ICT" OR "ICT, Finance"
    $names = [];
    foreach ((array)$staff_depts as $sd) {
        $did = (int)$sd['departmentid'];
        if (isset($map[$did])) $names[] = $map[$did];
    }

    $data['department_display'] = implode(', ', $names);           // for UI
    $data['department_id'] = !empty($staff_depts) ? (int)$staff_depts[0]['departmentid'] : 0;

        $data['title']      = _l('coi_disclosure_new');
        $data['staff_id']   = $staff_id;
        $data['staff_name'] = get_staff_full_name($staff_id);
         $data['staff_code'] = get_staff_inceif_staff_id($staff_id) ?: (string)$staff_id;
    $data['staff_position'] = get_staff_position($staff_id);
        $data['questions']  = $this->questions();

        $this->load->view('coi_disclosure/form', $data);
    }

    public function store()
    {
        if (!staff_can('create', 'coi_disclosure')) return $this->_deny();
        
        $year = (int)($this->input->post('year') ?: date('Y'));
        hc_enforce_submission_window($year, 'Submission closed. You can only submit up to 31 January.');

        $staff_id = (int)get_staff_user_id();
        $post     = $this->input->post(null, true);

        $signature = trim($post['signature'] ?? '');
        $sigDate   = $post['signed_date'] ?? date('Y-m-d');
        if ($signature === '') {
            set_alert('danger', 'Signature is required.');
            redirect(admin_url('coi_disclosure/create'));
        }

        $header = [
            'staff_id'    => $staff_id,
            'staff_name'  => get_staff_full_name($staff_id),
            'staff_code'  => $post['staff_code'] ?? (string)$staff_id,
            'position'    => $post['position'] ?? null,
            'department'  => $post['department'] ?? null,
            'department_id'          => $post['department_id'] ?? null,
            'signature'   => $signature,
            'signed_date' => $sigDate,
            'created_at'  => date('Y-m-d H:i:s'),
            'updated_at'  => null,
        ];

        $questions = $this->questions();
        $itemsPost = $post['items'] ?? [];
        $items = [];

      foreach ($questions as $idx => $q) {
    $no  = $idx + 1;

    // ✅ supports both formats:
    // - new format: ['text'=>..., 'placeholder'=>...]
    // - old format: 'string question'
    $questionText = is_array($q) ? ($q['text'] ?? '') : (string)$q;

    $ans = $itemsPost[$no]['answer'] ?? 'No';
    $det = $itemsPost[$no]['details'] ?? '';

    $items[] = [
        'question_no' => $no,
        'question'    => $questionText,  // ✅ string only
        'answer'      => $ans,
        'details'     => $det,
    ];
}


        $id = $this->coi_disclosure_model->create($header, $items);
        if (!$id) {
            set_alert('danger', 'Failed to save disclosure.');
            redirect(admin_url('coi_disclosure/create'));
        }

        // Upload attachments
        if (!empty($_FILES['attachments']) && !empty($_FILES['attachments']['name'][0])) {
            $path = coi_disclosure_upload_path($id);
            coi_disclosure_ensure_dir($path);

            $this->load->library('upload');
            $filesCount = count($_FILES['attachments']['name']);

            for ($i=0; $i<$filesCount; $i++) {
                if (empty($_FILES['attachments']['name'][$i])) continue;

                $_FILES['file']['name']     = $_FILES['attachments']['name'][$i];
                $_FILES['file']['type']     = $_FILES['attachments']['type'][$i];
                $_FILES['file']['tmp_name'] = $_FILES['attachments']['tmp_name'][$i];
                $_FILES['file']['error']    = $_FILES['attachments']['error'][$i];
                $_FILES['file']['size']     = $_FILES['attachments']['size'][$i];

                $config = [
                    'upload_path'   => $path,
                    'allowed_types' => coi_disclosure_allowed_types(),
                    'max_size'      => 10240,
                    'encrypt_name'  => true,
                ];
                $this->upload->initialize($config);

                if ($this->upload->do_upload('file')) {
                    $ud = $this->upload->data();
                    $this->coi_disclosure_model->add_file($id, $staff_id, [
                        'file_name'     => $ud['file_name'],
                        'original_name' => $ud['orig_name'],
                        'filetype'      => $ud['file_type'],
                        'filesize'      => $ud['file_size'],
                    ]);
                }
            }
        }

        //$this->coi_disclosure_model->log_activity('Submitted by '.get_staff_full_name($staff_id), $id);
        
        $prefix = $this->activity_prefix($id);
        log_activity($prefix . 'Submitted by ' . get_staff_full_name($staff_id), $staff_id);
        
        
        //$this->coi_disclosure_model->notify_recipients($id);

        set_alert('success', 'Submitted successfully.');
        redirect(admin_url('coi_disclosure/view/'.$id));
    }

   public function edit($id)
{
    if (!staff_can('edit', 'coi_disclosure')) return $this->_deny();

    $full = $this->coi_disclosure_model->get_full((int)$id);
    if (!$full) show_404();

    $decl   = $full['decl'];
    $logged = (int)get_staff_user_id();

    $canAll = staff_can('view', 'coi_disclosure');
    $canOwn = staff_can('view_own', 'coi_disclosure') && ((int)$decl['staff_id'] === $logged);
    if (!$canAll && !$canOwn) return $this->_deny();

    $staff_id = (int) ($full['decl']['staff_id'] ?? 0);
        $staff_depts = $this->departments_model->get_staff_departments($staff_id); // usually returns departmentid list
        $all_depts   = $this->departments_model->get(); // all departments with name

    // map id => name
    $map = [];
    foreach ((array)$all_depts as $d) {
        $map[(int)$d['departmentid']] = $d['name'];
    }

    // build display text: "ICT" OR "ICT, Finance"
    $names = [];
    foreach ((array)$staff_depts as $sd) {
        $did = (int)$sd['departmentid'];
        if (isset($map[$did])) $names[] = $map[$did];
    }

    $data['department_display'] = implode(', ', $names);           // for UI
    $data['department_id'] = !empty($staff_depts) ? (int)$staff_depts[0]['departmentid'] : 0;

    $data['is_edit']   = true;
    $data['decl']      = $decl;
    $data['items']     = $full['items'];
    $data['files']     = $full['files']; // ✅ IMPORTANT: so edit view can show attachments
    $data['questions'] = $this->questions();
    $data['title']     = 'Edit COI Disclosure #'.(int)$id;

    $this->load->view('coi_disclosure/form', $data);
}


public function update($id)
{
    if (!staff_can('edit', 'coi_disclosure')) {
        access_denied('coi_disclosure');
    }

    $id = (int)$id;
    $year = (int)($decl['year'] ?? date('Y'));
    hc_enforce_submission_window($year, 'Edits are closed after 31 January.');

    $full = $this->coi_disclosure_model->get_full($id);
    if (!$full) show_404();

    $decl   = $full['decl'];
    $logged = (int)get_staff_user_id();

    // respect view_all/view_own
    $canAll = staff_can('view', 'coi_disclosure');
    $canOwn = staff_can('view_own', 'coi_disclosure') && ((int)$decl['staff_id'] === $logged);
    if (!$canAll && !$canOwn) return $this->_deny();

    $post = $this->input->post(null, true);

    // ✅ Header update (keep staff identity untouched)
    $header = [
        'position'    => $post['position'] ?? ($decl['position'] ?? null),
        'department'  => $post['department'] ?? ($decl['department'] ?? null),
        'department_id'  => $post['department_id'] ?? ($decl['department_id'] ?? null),

        'signature'   => $post['signature'] ?? ($decl['signature'] ?? null),
        'signed_date' => $post['sigDate'] ?? $post['signed_date'] ?? ($decl['signed_date'] ?? null),
        'updated_at'  => date('Y-m-d H:i:s'),
    ];

    /**
     * ✅ Items:
     * Expecting form fields like:
     * items[1][answer]  items[1][details]
     * items[2][answer]  items[2][details]
     * ...
     */
    $items_in = $post['items'] ?? [];
    $items    = [];

    foreach ($items_in as $qno => $it) {
        $qno = (int)$qno;
        if ($qno <= 0) continue;

        $items[] = [
            'question_no' => $qno,
            'question'    => $it['question'] ?? null, // optional if you store question text
            'answer'      => $it['answer'] ?? 'No',
            'details'     => $it['details'] ?? '',
        ];
    }

    // ✅ Single call to your model method (updates header + replaces items)
    $this->coi_disclosure_model->update_declaration($id, $header, $items);

    // ✅ Replace all attachments (optional checkbox)
    if (!empty($post['replace_attachments'])) {
        $this->coi_disclosure_model->delete_all_files($id);
        $this->coi_delete_disk_folder($id);
    }

    // ✅ Append any newly uploaded attachments
    $this->coi_handle_uploads($id);

    //log_activity('COI Disclosure Updated (ID: '.$id.')', $logged);
    $prefix = $this->activity_prefix($id);
        log_activity($prefix . 'Updated by ' . get_staff_full_name($logged), $logged);
        
    set_alert('success', _l('updated_successfully', _l('coi_disclosure')));
    redirect(admin_url('coi_disclosure/edit/'.$id));
}

private function coi_handle_uploads($disclosure_id)
{
    if (empty($_FILES['attachments']) || empty($_FILES['attachments']['name'])) {
        return;
    }

    $path = FCPATH.'uploads/coi_disclosure/'.(int)$disclosure_id.'/';
    if (!is_dir($path)) {
        mkdir($path, 0755, true);
        file_put_contents($path.'index.html', '');
    }

    $this->load->library('upload');

    $names = $_FILES['attachments']['name'];
    $isMulti = is_array($names);
    $count   = $isMulti ? count($names) : 1;

    for ($i=0; $i<$count; $i++) {

        $_FILES['file']['name']     = $isMulti ? $_FILES['attachments']['name'][$i]     : $_FILES['attachments']['name'];
        $_FILES['file']['type']     = $isMulti ? $_FILES['attachments']['type'][$i]     : $_FILES['attachments']['type'];
        $_FILES['file']['tmp_name'] = $isMulti ? $_FILES['attachments']['tmp_name'][$i] : $_FILES['attachments']['tmp_name'];
        $_FILES['file']['error']    = $isMulti ? $_FILES['attachments']['error'][$i]    : $_FILES['attachments']['error'];
        $_FILES['file']['size']     = $isMulti ? $_FILES['attachments']['size'][$i]     : $_FILES['attachments']['size'];

        if (empty($_FILES['file']['name'])) continue;

        $config = [
            'upload_path'   => $path,
            'allowed_types' => 'pdf|doc|docx|jpg|jpeg|png',
            'max_size'      => 10240,
            'encrypt_name'  => true,
        ];

        $this->upload->initialize($config);

        if ($this->upload->do_upload('file')) {
            $ud = $this->upload->data();
            $this->coi_disclosure_model->add_file($disclosure_id, get_staff_user_id(), [
                'file_name'     => $ud['file_name'],
                'original_name' => $ud['orig_name'],
                'filetype'      => $ud['file_type'],
                'filesize'      => $ud['file_size'],
            ]);
        } else {
            log_message('error', 'COI upload error: '.$this->upload->display_errors('', ''));
        }
    }
}

private function coi_delete_disk_folder($disclosure_id)
{
    $dir = FCPATH.'uploads/coi_disclosure/'.(int)$disclosure_id.'/';
    if (!is_dir($dir)) return;

    $files = glob($dir.'*');
    if ($files) {
        foreach ($files as $f) {
            if (is_file($f) && basename($f) !== 'index.html') @unlink($f);
        }
    }
}
public function delete_file($disclosure_id, $file_id)
{
    if (!staff_can('edit', 'coi_disclosure') && !staff_can('delete', 'coi_disclosure')) {
        access_denied('coi_disclosure');
    }

    $disclosure_id = (int)$disclosure_id;
    $file_id       = (int)$file_id;

    $file = $this->coi_disclosure_model->get_file($file_id);
    if (!$file || (int)$file['disclosure_id'] !== $disclosure_id) {
        echo json_encode(['success' => false, 'message' => 'File not found.']);
        die;
    }

    // delete disk
    $full = FCPATH.'uploads/coi_disclosure/'.$disclosure_id.'/'.$file['file_name'];
    if (file_exists($full)) @unlink($full);

    // delete db
    $this->coi_disclosure_model->delete_file($file_id);

    log_activity('COI Attachment Deleted [Disclosure ID: '.$disclosure_id.', File ID: '.$file_id.']', get_staff_user_id());

    echo json_encode(['success' => true]);
    die;
}
private function activity_prefix($id)
{
    return '[COI Disclosure #' . (int)$id . '] ';
}
    public function update_OLD($id)
    {
        if (!staff_can('edit', 'coi_disclosure')) return $this->_deny();

        $full = $this->coi_disclosure_model->get_full((int)$id);
        if (!$full) show_404();

        $decl = $full['decl'];
        $logged = (int)get_staff_user_id();

        $canAll = staff_can('view', 'coi_disclosure');
        $canOwn = staff_can('view_own', 'coi_disclosure') && ((int)$decl['staff_id'] === $logged);
        if (!$canAll && !$canOwn) return $this->_deny();

        $post = $this->input->post(null, true);

        $signature = trim($post['signature'] ?? '');
        $sigDate   = $post['signed_date'] ?? date('Y-m-d');
        if ($signature === '') {
            set_alert('danger', 'Signature is required.');
            redirect(admin_url('coi_disclosure/edit/'.$id));
        }

        $header = [
            'position'   => $post['position'] ?? null,
            'department' => $post['department'] ?? null,
            'signature'  => $signature,
            'signed_date'=> $sigDate,
            'updated_at' => date('Y-m-d H:i:s'),
        ];

        $questions = $this->questions();
        $itemsPost = $post['items'] ?? [];
        $items = [];

        foreach ($questions as $idx => $qText) {
            $no = $idx + 1;
            $items[] = [
                'question_no' => $no,
                'question'    => $qText,
                'answer'      => $itemsPost[$no]['answer'] ?? 'No',
                'details'     => $itemsPost[$no]['details'] ?? '',
            ];
        }

        $this->coi_disclosure_model->update_declaration((int)$id, $header, $items);
        $this->coi_disclosure_model->log_activity('Updated by '.get_staff_full_name($logged), (int)$id);

        set_alert('success', 'Updated successfully.');
        redirect(admin_url('coi_disclosure/view/'.$id));
    }

    public function view($id)
    {
        if (staff_cant('view', 'coi_disclosure') && staff_cant('view_own', 'coi_disclosure')) {
            return $this->_deny();
        }

        $full = $this->coi_disclosure_model->get_full((int)$id);
        if (!$full) show_404();

        $decl = $full['decl'];
        $logged = (int)get_staff_user_id();

        $canAll = staff_can('view', 'coi_disclosure');
        $canOwn = staff_can('view_own', 'coi_disclosure') && ((int)$decl['staff_id'] === $logged);
        if (!$canAll && !$canOwn) return $this->_deny();

        $data['decl']          = $decl;
        $data['items']         = $full['items'];
        $data['files']         = $full['files'];
        $data['activity_logs'] = $this->coi_disclosure_model->get_activity_logs((int)$id, 80);
        $data['title']         = _l('coi_disclosure_view').' #'.(int)$id;

        $this->load->view('coi_disclosure/view', $data);
    }

    public function delete($id)
    {
        if (!staff_can('delete', 'coi_disclosure')) return $this->_deny();

        $decl = $this->coi_disclosure_model->get((int)$id);
        if (!$decl) show_404();

        $logged = (int)get_staff_user_id();
        $canAll = staff_can('view', 'coi_disclosure');
        $canOwn = staff_can('view_own', 'coi_disclosure') && ((int)$decl['staff_id'] === $logged);
        if (!$canAll && !$canOwn) return $this->_deny();

        $this->coi_disclosure_model->delete((int)$id);
        $this->coi_disclosure_model->log_activity('Deleted by '.get_staff_full_name($logged), (int)$id);

        set_alert('success', 'Deleted successfully.');
        redirect(admin_url('coi_disclosure'));
    }

    public function download_file($disclosure_id, $file_id)
    {
        $full = $this->coi_disclosure_model->get_full((int)$disclosure_id);
        if (!$full) show_404();

        $decl = $full['decl'];
        $logged = (int)get_staff_user_id();

        $canAll = staff_can('view', 'coi_disclosure');
        $canOwn = staff_can('view_own', 'coi_disclosure') && ((int)$decl['staff_id'] === $logged);
        if (!$canAll && !$canOwn) return $this->_deny();

        $file = $this->coi_disclosure_model->get_file((int)$file_id);
        if (!$file) show_404();

        $path = coi_disclosure_upload_path((int)$disclosure_id) . $file['file_name'];
        if (!file_exists($path)) show_404();

        $this->load->helper('download');
        force_download($file['original_name'] ?: $file['file_name'], file_get_contents($path));
    }




    /**
     * Export all disclosures to Excel (xlsx)
     * Columns: header fields + Q1..Q15 (Answer + Details)
     */
    public function export_excel()
{
    if (staff_cant('view', 'coi_disclosure') && staff_cant('view_own', 'coi_disclosure')) {
        access_denied('coi_disclosure');
    }

    $can_view_all = staff_can('view', 'coi_disclosure');
    $staff_id     = get_staff_user_id();

    // Support:
    // - POST ids[] from selected rows
    // - GET ?id=123 to export one
    $ids = $this->input->post('ids');
    if (!$ids) {
        $single = $this->input->get('id');
        if ($single) $ids = [(int)$single];
    }
    if (!is_array($ids)) $ids = [];

    // rows are "flattened": 1 row per disclosure with Q columns
    $rows = $this->coi_disclosure_model->get_export_rows($ids, $staff_id, $can_view_all);

    // Columns
    $headers = [
        'Disclosure ID',
        'Name',
        'Staff ID',
        'Position',
        'Department',
        'Signature',
        'Signed Date',
        'Created',
        'Updated',
        'Yes Count',
    ];

    // Q1..Q15 Answer + Details
    for ($i = 1; $i <= 8; $i++) {
        $headers[] = "Q{$i} Answer";
        $headers[] = "Q{$i} Details";
    }

    // Try XLSX with PhpSpreadsheet if available, otherwise CSV fallback
    if (class_exists(\PhpOffice\PhpSpreadsheet\Spreadsheet::class)) {

        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('COI Disclosures');

        // Header row
        $col = 1;
        foreach ($headers as $h) {
            $sheet->setCellValueByColumnAndRow($col++, 1, $h);
        }

        // Data
        $r = 2;
        foreach ($rows as $x) {

            $dataRow = [
                $x['disclosure_id'],
                $x['staff_name'],
                $x['staff_code'] ?: $x['staff_id'],
                $x['position'],
                $x['department'],
                $x['signature'],
                $x['signed_date'],
                $x['created_at'],
                $x['updated_at'] ?: '-',
                (int)($x['yes_count'] ?? 0),
            ];

            for ($i = 1; $i <= 15; $i++) {
                $dataRow[] = $x["q{$i}_answer"] ?? 'No';
                $dataRow[] = $x["q{$i}_details"] ?? '';
            }

            $col = 1;
            foreach ($dataRow as $val) {
                $sheet->setCellValueByColumnAndRow($col++, $r, $val);
            }

            $r++;
        }

        // Autosize columns
        for ($i = 1; $i <= count($headers); $i++) {
            $sheet->getColumnDimensionByColumn($i)->setAutoSize(true);
        }

        // Output
        $filename = 'coi_disclosures_' . date('Ymd_His') . '.xlsx';
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment; filename="'.$filename.'"');
        header('Cache-Control: max-age=0');

        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        $writer->save('php://output');
        exit;

    } else {

        // CSV fallback (always works)
        $filename = 'coi_disclosures_' . date('Ymd_His') . '.csv';
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="'.$filename.'"');

        $out = fopen('php://output', 'w');
        fputcsv($out, $headers);
        $xyz = '`';

        foreach ($rows as $x) {

            $csvRow = [
                $x['disclosure_id'],
                $x['staff_name'],
                $xyz.$x['staff_code'] ?: $x['staff_id'],
                $x['position'],
                $x['department'],
                $x['signature'],
                $x['signed_date'],
                $x['created_at'],
                $x['updated_at'] ?: '-',
                (int)($x['yes_count'] ?? 0),
            ];

            for ($i = 1; $i <= 15; $i++) {
                $csvRow[] = $x["q{$i}_answer"] ?? 'No';
                $csvRow[] = $x["q{$i}_details"] ?? '';
            }

            fputcsv($out, $csvRow);
        }

        fclose($out);
        exit;
    }
}

    public function export_excel__OLD()
    {
        if (staff_cant('view', 'coi_disclosure') && staff_cant('view_own', 'coi_disclosure')) {
            access_denied('coi_disclosure');
        }

        // view_own restriction
        $onlyOwn = (staff_cant('view', 'coi_disclosure') && staff_can('view_own', 'coi_disclosure'));
        $staffId = $onlyOwn ? get_staff_user_id() : null;

        $decls = $this->coi_disclosure_model->get_all_for_export($staffId);

        if (!$decls || count($decls) === 0) {
            set_alert('warning', 'No records to export.');
            redirect(admin_url('coi_disclosure'));
        }

        // Load PhpSpreadsheet (Perfex usually ships it)
        if (!class_exists('\PhpOffice\PhpSpreadsheet\Spreadsheet')) {
            // Try to include composer autoload if present
            $autoload = FCPATH . 'vendor/autoload.php';
            if (file_exists($autoload)) {
                require_once($autoload);
            }
        }

        if (!class_exists('\PhpOffice\PhpSpreadsheet\Spreadsheet')) {
            show_error('PhpSpreadsheet not available. Please ensure vendor/autoload.php exists or PhpSpreadsheet is installed.');
        }

        $questions = $this->coi_questions(); // [1 => 'question text', ...]

        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('COI Disclosures');

        // Header row
        $col = 1;
        $headers = [
            'ID',
            'Name',
            'Staff ID',
            'Position',
            'Department',
            'Signature',
            'Signed Date',
            'Created',
            'Updated',
            'Yes Count',
        ];

        foreach ($headers as $h) {
            $sheet->setCellValueByColumnAndRow($col++, 1, $h);
        }

        // Q columns
        foreach ($questions as $no => $qText) {
            $sheet->setCellValueByColumnAndRow($col++, 1, "Q{$no} Answer");
            $sheet->setCellValueByColumnAndRow($col++, 1, "Q{$no} Details");
        }

        // Data rows
        $row = 2;
        foreach ($decls as $d) {
            // build map: [question_no => ['answer'=>'Yes/No','details'=>'...']]
            $itemsMap = $this->coi_disclosure_model->get_items_map($d['id']);

            // yes count
            $yesCount = 0;
            foreach ($itemsMap as $it) {
                if (strtolower(trim($it['answer'] ?? 'no')) === 'yes') $yesCount++;
            }

            $col = 1;
            $sheet->setCellValueByColumnAndRow($col++, $row, (int)$d['id']);
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['staff_name'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['staff_code'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['position'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['department'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['signature'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['signed_date'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['created_at'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, (string)($d['updated_at'] ?? ''));
            $sheet->setCellValueByColumnAndRow($col++, $row, $yesCount);

            foreach ($questions as $no => $qText) {
                $ans = $itemsMap[$no]['answer'] ?? 'No';
                $det = $itemsMap[$no]['details'] ?? '';
                $sheet->setCellValueByColumnAndRow($col++, $row, $ans);
                $sheet->setCellValueByColumnAndRow($col++, $row, $det);
            }

            $row++;
        }

        // style header row bold
        $lastCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col - 1);
        $sheet->getStyle("A1:{$lastCol}1")->getFont()->setBold(true);
        $sheet->freezePane('A2');

        // autosize columns (safe for modest data)
        for ($i = 1; $i <= ($col - 1); $i++) {
            $sheet->getColumnDimensionByColumn($i)->setAutoSize(true);
        }

        $filename = 'coi_disclosures_' . date('Ymd_His') . '.xlsx';

        // Output
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        $writer->save('php://output');
        exit;
    }

    /**
     * PDF for a single COI disclosure (HTML -> TCPDF)
     */
    public function pdf($id)
    {
        if (staff_cant('view', 'coi_disclosure') && staff_cant('view_own', 'coi_disclosure')) {
            access_denied('coi_disclosure');
        }

        $id = (int)$id;
        $decl = $this->coi_disclosure_model->get($id);

        if (!$decl) {
            show_404();
        }

        // view_own restriction
        if (staff_cant('view', 'coi_disclosure') && staff_can('view_own', 'coi_disclosure')) {
            if ((int)$decl['staff_id'] !== (int)get_staff_user_id()) {
                access_denied('coi_disclosure');
            }
        }

        $data = [];
        $data['decl']      = $decl;
        $data['items_map'] = $this->coi_disclosure_model->get_items_map($id);
        $data['questions'] = $this->coi_questions();
        $data['files']     = $this->coi_disclosure_model->get_files($id);

        // Render HTML
        $html = $this->load->view('coi_disclosure/pdf', $data, true);

        // Use Perfex PDF library (TCPDF)
        // Perfex uses TCPDF internally. :contentReference[oaicite:1]{index=1}
        $pdf = null;

        if (class_exists('Pdf')) {
            $pdf = new Pdf();
        } elseif (class_exists('TCPDF')) {
            $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
        } else {
            show_error('TCPDF/Pdf library not available.');
        }

        $pdf->SetTitle('COI Disclosure #' . $id);
        $pdf->SetMargins(12, 12, 12);
        $pdf->SetAutoPageBreak(true, 12);
        $pdf->AddPage();

        // writeHTML: main render
        $pdf->writeHTML($html, true, false, true, false, '');

        $filename = 'COI_Disclosure_' . $id . '.pdf';
        $pdf->Output($filename, 'I');
        exit;
    }

    /**
     * Your COI questions (15 items)
     * Keep this as the single source of truth for PDF + Excel.
     */
    private function coi_questions()
    {
        return [
            1  => 'Have you or any affiliated persons provided goods, services, or property to INCEIF? (If Yes, PCEO approval is required)',
            2  => 'Have you or any affiliated persons purchased goods, services, or property from INCEIF? (If Yes, PCEO approval is required)',
            3  => 'Do you or any affiliated persons hold any equity or financial interest in entities doing business with INCEIF (e.g., suppliers, vendors, partners)? (If Yes, PCEO approval is required)',
            4  => 'Have you or any affiliated persons received any gifts exceeding RM200 or benefits likely to influence decisions? (If Yes, please also submit the Gift Disclosure Form)',
            5  => 'Have you received hospitality, entertainment, or other benefits that may be perceived as excessive, lavish, frequent, or unrelated to INCEIF business? (If Yes, please also submit the Gift Disclosure Form)',
            6  => 'Are you or any affiliated persons a party to any legal proceedings currently pending or recently resolved involving INCEIF? (If Yes, PCEO approval is required)',
            7  => 'Have you or any family members entered into contractual agreements with INCEIF (e.g., leases, sales, services)? (If Yes, PCEO approval is required)',
            8  => 'Are you or any affiliated persons indebted to INCEIF (other than travel or expense advances)? (If Yes, PCEO approval is required)',
            9  => 'Have you or any affiliated persons received personal benefits from INCEIF outside normal employment terms? (If Yes, PCEO approval is required)',
            10 => 'Do your family members or connected parties have business dealings or financial interests with any INCEIF vendors, contractors, or partners? (If Yes, PCEO approval is required)',
            11 => 'Have you used or permitted the use of INCEIF resources (e.g., facilities, name, funds, intellectual property, confidential information) for non-INCEIF purposes? (If Yes, PCEO approval is required)',
            12 => 'Are you involved in hiring, assessing, or supervising individuals with whom you have a close personal, family, or financial relationship? (If Yes, PCEO approval is required)',
            13 => 'Were you or any affiliated persons involved in external employment, directorships, consultancies, or other engagements (paid or unpaid)? (If Yes, please also submit the External Engagement Declaration Form)',
            14 => 'Are you engaged in public training, consulting, or speaking for competitor institutions where topics, content, or audiences may overlap with INCEIF offerings? (If Yes, please also submit the External Engagement Declaration Form)',
            15 => 'Are you aware of any other events, transactions, arrangements, or circumstances (past, present, or anticipated) that may give rise to an actual, potential, or perceived conflict of interest with your duties at INCEIF? (If Yes, PCEO approval is required)',
        ];
    }



    public function settings()
{
    if (!is_admin()) access_denied('coi_disclosure');

    $data['title'] = 'COI Disclosure Settings';
    $data['roles'] = $this->db->get(db_prefix().'roles')->result_array();

    $data['selected_role_ids']  = array_filter(array_map('intval', explode(',', (string)get_option('coi_notify_role_ids'))));
    $data['selected_staff_ids'] = array_filter(array_map('intval', explode(',', (string)get_option('coi_notify_staff_ids'))));

    $data['staff'] = $this->db->select('staffid,firstname,lastname,email')
        ->from(db_prefix().'staff')->where('active', 1)->get()->result_array();

    $data['form_action'] = admin_url('coi_disclosure/settings');
    $data['back_url']    = admin_url('coi_disclosure');

    if ($this->input->post()) {
        update_option('coi_notify_role_ids', implode(',', (array)$this->input->post('role_ids')));
        update_option('coi_notify_staff_ids', implode(',', (array)$this->input->post('staff_ids')));
        set_alert('success', 'Settings saved');
        redirect(admin_url('coi_disclosure/settings'));
    }

    $this->load->view('coi_disclosure/settings', $data);
}

}



