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

class Staff_declaration extends AdminController
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('staff_declaration_model');
        $this->load->helper('staff_declaration/staff_declaration');
    }

    private function _deny()
    {
        set_alert('warning', _l('staff_declaration_no_permission'));
        redirect(admin_url());
    }

    public function index()
    {
        if (!staff_can('view', 'staff_declaration') && !staff_can('view_own', 'staff_declaration')) {
            return $this->_deny();
        }

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

        $data['title'] = _l('staff_declaration_manage');
        $data['rows']  = $this->staff_declaration_model->all_for_staff($staff_id, $can_view_all);

        $this->load->view('staff_declaration/manage', $data);
    }
    public function table()
{
    if (staff_cant('view', 'staff_declaration') && staff_cant('view_own', 'staff_declaration')) {
        access_denied('staff_declaration');
    }

    // This will load the tables file and echo JSON
    $this->app->get_table_data(module_views_path('staff_declaration', 'tables/staff_declarations'));
}

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

         $this->load->model('departments_model');
        
    $staff_id = 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('staff_declaration_new');
        $data['staff_id']  = $staff_id;
        $data['staff_code'] = get_staff_inceif_staff_id($staff_id) ?: (string)$staff_id;
    $data['staff_position'] = get_staff_position($staff_id);
        $data['staff_name']= get_staff_full_name($staff_id); // auto from system (readonly)

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

   public function store()
{
    if (!staff_can('create', 'staff_declaration')) {
        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);

    // Items come as items[0][date_received]...
    $items = $post['items'] ?? [];
    $clean_items = [];

    foreach ($items as $r) {
        $hasAny =
            trim(($r['category'] ?? '')) !== '' ||
            trim(($r['description'] ?? '')) !== '' ||
            trim(($r['gift_from'] ?? '')) !== '' ||
            trim(($r['estimated_value'] ?? '')) !== '' ||
            trim(($r['relationship'] ?? '')) !== '' ||
            trim(($r['purpose'] ?? '')) !== '' ||
            trim(($r['action_taken'] ?? '')) !== '' ||
            trim(($r['date_received'] ?? '')) !== '';

        if (!$hasAny) {
            continue;
        }

        $clean_items[] = [
            'date_received'   => $r['date_received'] ?? null,
            'category'     => $r['category'] ?? null,
            'description'     => $r['description'] ?? null,
            'estimated_value' => $r['estimated_value'] ?? null,
            'gift_from'       => $r['gift_from'] ?? null,
            'relationship'    => $r['relationship'] ?? null,
            'purpose'         => $r['purpose'] ?? null,
            'action_taken'    => $r['action_taken'] ?? null,
        ];
    }

    // Minimal validation (recommended)
    $signature = trim($post['employee_signature'] ?? '');
    $emp_date  = $post['employee_date'] ?? date('Y-m-d');

    if ($signature === '') {
        set_alert('danger', 'Signature is required.');
        redirect(admin_url('staff_declaration/create'));
    }

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


        $hod_id = $this->staff_declaration_model->get_hod_staff_id($staff_id); // reads tblstaff.hod
        if (empty($hod_id)) {
        set_alert('danger', 'Your HOD is not set in Staff profile. Please contact admin.');
        redirect(admin_url('staff_declaration/create'));
        }

        $header['hod_id'] = $hod_id ?: null;
       
        $header['status']       = 'pending_hod';

    $declaration_id = $this->staff_declaration_model->create($header, $clean_items);

    if (!$declaration_id) {
        set_alert('danger', 'Failed to save declaration.');
        redirect(admin_url('staff_declaration/create'));
    }

    $prefix = $this->activity_prefix($declaration_id);

    // Handle multi upload (ONLY after successful create)
    if (!empty($_FILES['attachments']) && !empty($_FILES['attachments']['name'][0])) {

        $path = staff_declaration_upload_path($declaration_id);
        staff_declaration_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' => staff_declaration_allowed_types(),
                'max_size'      => 10240, // 10MB
                'encrypt_name'  => true,
            ];

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

            if ($this->upload->do_upload('file')) {
                $ud = $this->upload->data();

                $this->staff_declaration_model->add_file($declaration_id, $staff_id, [
                    'file_name'     => $ud['file_name'],
                    'original_name' => $ud['orig_name'],
                    'filetype'      => $ud['file_type'],
                    'filesize'      => $ud['file_size'],
                ]);
            } else {
                // Optional: log upload error (helps debugging)
                log_activity($prefix . 'Attachment upload failed: ' . $this->upload->display_errors('', ''), $staff_id);
            }
        }
    }

    // Log submitted + notify
    log_activity($prefix . 'Submitted by ' . get_staff_full_name($staff_id), $staff_id);

     
     $this->_notify_hod($declaration_id, $staff_id);

    // IMPORTANT: use $declaration_id (not $id)
    //$this->staff_declaration_model->notify_recipients($declaration_id);

    set_alert('success', _l('staff_declaration_saved'));
    redirect(admin_url('staff_declaration/view/' . $declaration_id));
}


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

    $data = $this->staff_declaration_model->get($id);
    if (!$data || empty($data['decl'])) {
        set_alert('warning', _l('staff_declaration_not_found'));
        return redirect(admin_url('staff_declaration'));
    }

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

    $canAll  = staff_can('view', 'staff_declaration');
    $isOwner = ((int)($decl['staff_id'] ?? 0) === $logged);
    $isHod   = ((int)($decl['hod_id'] ?? 0) === $logged);

    // ✅ One single permission gate: allow (view all) OR (owner) OR (hod)
    if (!$canAll && !$isOwner && !$isHod) {
        return $this->_deny();
    }

    // Optional helper (must accept $decl OR handle correctly)
    if (function_exists('see_can_view_staff_declaration')) {
        if (!see_can_view_staff_declaration($decl)) {
            access_denied('staff_declaration');
        }
    }

    $data['activity_logs'] = $this->staff_declaration_model->get_activity_logs($id);
    $data['is_owner']      = $isOwner;
    $data['is_hod']        = $isHod;

    // ✅ can edit only if owner AND still pending (HOD not acted yet)
    $data['can_edit'] = $isOwner && (($decl['hod_status'] ?? 'pending') === 'pending');

    $data['title'] = _l('staff_declaration_view');
    $this->load->view('staff_declaration/view', $data);
}


    public function download_file($declaration_id, $file_id)
    {
        $data = $this->staff_declaration_model->get($declaration_id);
        if (!$data) show_404();

        if (!staff_can('view', 'staff_declaration') && (int)$data['decl']['staff_id'] !== (int)get_staff_user_id()) {
            return $this->_deny();
        }

        $fileRow = null;
        foreach ($data['files'] as $f) {
            if ((int)$f['id'] === (int)$file_id) { $fileRow = $f; break; }
        }
        if (!$fileRow) show_404();

        $path = staff_declaration_upload_path($declaration_id) . $fileRow['file_name'];
        if (!is_file($path)) show_404();

        $this->load->helper('download');
        $staff_id = get_staff_user_id();
log_activity(
    $this->activity_prefix($declaration_id) . 'Downloaded attachment: ' . ($fileRow['original_name'] ?: $fileRow['file_name']),
    $staff_id
);

        force_download($fileRow['original_name'] ?: $fileRow['file_name'], file_get_contents($path));
    }


    public function pdf__NEW($id)
{
    if (staff_cant('view', 'staff_declaration') && staff_cant('view_own', 'staff_declaration')) {
        access_denied('staff_declaration');
    }

    $id = (int)$id;

    $full = $this->staff_declaration_model->get($id);
    if (!$full) {
        show_404();
    }

    // Permission: view_own
    $decl = $full['decl'];
    $logged = (int)get_staff_user_id();

    $canAll = staff_can('view', 'staff_declaration');
    $canOwn = staff_can('view_own', 'staff_declaration') && ((int)$decl['staff_id'] === $logged);

    if (!$canAll && !$canOwn) {
        access_denied('staff_declaration');
    }

    // IMPORTANT: clear any previous output buffers
    while (ob_get_level() > 0) {
        ob_end_clean();
    }

    // Build PDF
    $pdf = staff_declaration_pdf($full); // <-- your helper should return App_pdf instance
    $filename = 'gift_disclosure_'.$id.'.pdf';

    // Output
    $pdf->Output($filename, 'I');
    exit;
}


    public function pdf($id)
    {
        $data = $this->staff_declaration_model->get($id);
        if (!$data) show_404();

        if (!staff_can('view', 'staff_declaration') && (int)$data['decl']['staff_id'] !== (int)get_staff_user_id()) {
            return $this->_deny();
        }
        $staff_id = get_staff_user_id();
         // IMPORTANT: clear any previous output buffers
   
    // IMPORTANT: clear any previous output buffers
   
        $pdf = staff_declaration_pdf($data);
        // Build HTML from view
        //$html = $this->load->view('staff_declaration/pdf_template', $data, true);

        // TCPDF (Perfex uses TCPDF for PDFs)
        // $this->load->library('tcpdf');

        // $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
        // $pdf->SetCreator('Perfex CRM');
        // $pdf->SetTitle('Gift Disclosure Form #' . $id);
        // $pdf->SetMargins(12, 12, 12);
        // $pdf->AddPage();
        // $pdf->writeHTML($html, true, false, true, false, '');
        // $staff_id = get_staff_user_id();
        log_activity($this->activity_prefix($id) . 'Exported PDF by ' . get_staff_full_name($staff_id), $staff_id);
        // if (headers_sent($file, $line)) {
        // die("Headers already sent in $file on line $line");
        // }


        $pdf->Output('gift-disclosure-'.$id.'.pdf', 'D');

    }

    public function edit($id)
{
    $data = $this->staff_declaration_model->get($id);
    if (!$data) show_404();

    if (!$this->_can_edit_record($data['decl'])) {
        return $this->_deny();
    }

     $staff_id = (int) ($data['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];
    }
    
$st = $data['decl']['status'] ?? 'pending';
// Only allow edit when pending / to approve
$data['canEdit'] = ( !in_array($st, ['approved','rejected'], true));
$data['status']  = $st;

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

    $data['title']   = 'Edit Declaration #' . (int)$id;
    $data['is_edit'] = true;

    $this->load->view('staff_declaration/form', $data);
}
public function update($id)
{
    $data = $this->staff_declaration_model->get($id);
    if (!$data) show_404();

    
     $st   = $data['decl']['status'] ?? 'pending';
    
     $year = (int)($decl['year'] ?? date('Y'));
     hc_enforce_submission_window($year, 'Edits are closed after 31 January.');
     
       if (in_array($st, ['approved', 'rejected'], true)) {
        access_denied('staff_declaration'); // or $this->_deny();
    }


    if (!$this->_can_edit_record($data['decl'])) {
        return $this->_deny();
    }
    
  

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

    // Build items array from POST (same as store())
    $items = $post['items'] ?? [];
    $clean_items = [];

    foreach ($items as $r) {
        $hasAny = trim(($r['category'] ?? '')) !== '' ||
                  trim(($r['description'] ?? '')) !== '' ||
                  trim(($r['gift_from'] ?? '')) !== '' ||
                  trim(($r['estimated_value'] ?? '')) !== '' ||
                  trim(($r['relationship'] ?? '')) !== '' ||
                  trim(($r['purpose'] ?? '')) !== '' ||
                  trim(($r['action_taken'] ?? '')) !== '' ||
                  trim(($r['date_received'] ?? '')) !== '';

        if (!$hasAny) continue;

        $clean_items[] = [
            'date_received'   => $r['date_received'] ?? null,
            'category'     => $r['category'] ?? null,
            'description'     => $r['description'] ?? null,
            'estimated_value' => $r['estimated_value'] ?? null,
            'gift_from'       => $r['gift_from'] ?? null,
            'relationship'    => $r['relationship'] ?? null,
            'purpose'         => $r['purpose'] ?? null,
            'action_taken'    => $r['action_taken'] ?? null,
        ];
    }

    $header = [
        // keep staff_id/staff_name unchanged (source of truth)
        'position'           => $post['position'] ?? null,
        'department'         => $post['department'] ?? null,
          'department_id'         => $post['department_id'] ?? null,
        'employee_signature' => $post['employee_signature'],
        'employee_date'      => $post['employee_date'],
        'updated_at'         => date('Y-m-d H:i:s'),
    ];

    $this->staff_declaration_model->update_declaration($id, $header, $clean_items);

    // Optional: allow adding NEW attachments on edit
    $uploadedNames = [];
    if (!empty($_FILES['attachments']) && !empty($_FILES['attachments']['name'][0])) {
        $path = staff_declaration_upload_path($id);
        staff_declaration_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' => staff_declaration_allowed_types(),
                'max_size'      => 10240,
                'encrypt_name'  => true,
            ];

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

            if ($this->upload->do_upload('file')) {
                $ud = $this->upload->data();

                $this->staff_declaration_model->add_file($id, $staff_id, [
                    'file_name'      => $ud['file_name'],
                    'original_name'  => $ud['orig_name'],
                    'filetype'       => $ud['file_type'],
                    'filesize'       => $ud['file_size'],
                ]);

                $uploadedNames[] = $ud['orig_name'];
            }
        }
    }

    // Activity log (built-in)
    $prefix = $this->activity_prefix($id);
    log_activity($prefix . 'Updated by ' . get_staff_full_name($staff_id), $staff_id);

    if (!empty($uploadedNames)) {
        log_activity($prefix . 'Uploaded attachments (edit): ' . implode(', ', $uploadedNames), $staff_id);
    }

    set_alert('success', 'Declaration updated successfully.');
    redirect(admin_url('staff_declaration/view/'.$id));
}
public function delete($id)
{
    $data = $this->staff_declaration_model->get($id);
    if (!$data) show_404();

    if (!$this->_can_delete_record($data['decl'])) {
        return $this->_deny();
    }

    $staff_id = get_staff_user_id();
    $prefix   = $this->activity_prefix($id);

    // Delete db rows and get file list to remove from disk
    $files = $this->staff_declaration_model->delete_declaration($id);

    // Remove physical files + folder
    $basePath = staff_declaration_upload_path($id);
    if (!empty($files)) {
        foreach ($files as $f) {
            $p = $basePath . $f['file_name'];
            if (is_file($p)) @unlink($p);
        }
    }
    if (is_dir($basePath)) {
        @rmdir($basePath); // will only remove if empty
    }

    log_activity($prefix . 'Deleted by ' . get_staff_full_name($staff_id), $staff_id);

    set_alert('success', 'Declaration deleted.');
    redirect(admin_url('staff_declaration'));
}
public function delete_file($declaration_id, $file_id)
{
    $data = $this->staff_declaration_model->get($declaration_id);
    if (!$data) show_404();

    if (!$this->_can_edit_record($data['decl'])) {
        return $this->_deny();
    }

    $staff_id = get_staff_user_id();
    $prefix   = $this->activity_prefix($declaration_id);

    $row = $this->staff_declaration_model->delete_file_row($declaration_id, $file_id);
    if ($row) {
        $path = staff_declaration_upload_path($declaration_id) . $row['file_name'];
        if (is_file($path)) @unlink($path);

        log_activity($prefix . 'Attachment deleted: ' . ($row['original_name'] ?: $row['file_name']), $staff_id);
        set_alert('success', 'Attachment removed.');
    } else {
        set_alert('warning', 'Attachment not found.');
    }

    redirect(admin_url('staff_declaration/view/'.$declaration_id));
}




    private function _can_access_record($declRow)
{
    $staff_id = get_staff_user_id();

    // global view allowed
    if (staff_can('view', 'staff_declaration')) return true;

    // own view allowed
    if (staff_can('view_own', 'staff_declaration') && (int)$declRow['staff_id'] === (int)$staff_id) return true;

    return false;
}

private function _can_edit_record($declRow)
{
    $staff_id = get_staff_user_id();

    // must have edit capability
    if (!staff_can('edit', 'staff_declaration')) return false;

    // global edit if view global
    if (staff_can('view', 'staff_declaration')) return true;

    // own edit
    return staff_can('view_own', 'staff_declaration') && (int)$declRow['staff_id'] === (int)$staff_id;
}

private function _can_delete_record($declRow)
{
    $staff_id = get_staff_user_id();

    if (!staff_can('delete', 'staff_declaration')) return false;

    if (staff_can('view', 'staff_declaration')) return true;

    return staff_can('view_own', 'staff_declaration') && (int)$declRow['staff_id'] === (int)$staff_id;
}

private function activity_prefix($id)
{
    return '[Staff Declaration #' . (int)$id . '] ';
}

public function export_excel()
{
    if (staff_cant('view', 'staff_declaration') && staff_cant('view_own', 'staff_declaration')) {
        access_denied('staff_declaration');
    }

    $can_view_all = staff_can('view', 'staff_declaration');
    $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 = $this->staff_declaration_model->get_export_rows($ids, $staff_id, $can_view_all);

    // Columns
    $headers = [
        'Declaration ID',
        'Name',
        'Staff ID',
        'Position',
        'Department',
        'Signature',
        'Declaration Date',
        'Created',
        'Updated',
        'Gift No',
        'Gift Date',
        'Category',
        'Description',
        'Value (RM)',
        'From',
        'Relationship',
        'Purpose',
        'Action',
    ];

    // 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('Declarations');

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

        // Data
        $r = 2;
        foreach ($rows as $x) {
            $giftNo = $x['sort_order'] ? (int)$x['sort_order'] : '';
            $dataRow = [
                $x['declaration_id'],
                $x['staff_name'],
                $x['staff_code'] ?: $x['staff_id'],
                $x['position'],
                $x['department'],
                $x['employee_signature'],
                $x['employee_date'],
                $x['created_at'],
                $x['updated_at'] ?: '-',
                $giftNo,
                $x['date_received'],
                $x['category'],
                $x['description'],
                $x['estimated_value'],
                $x['gift_from'],
                $x['relationship'],
                $x['purpose'],
                $x['action_taken'],
            ];

            $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 = 'staff_declarations_' . 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 = 'staff_declarations_' . 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);

        foreach ($rows as $x) {
            fputcsv($out, [
                $x['declaration_id'],
                $x['staff_name'],
                $x['staff_code'] ?: $x['staff_id'],
                $x['position'],
                $x['department'],
                $x['employee_signature'],
                $x['employee_date'],
                $x['created_at'],
                $x['updated_at'] ?: '-',
                $x['sort_order'] ? (int)$x['sort_order'] : '',
                $x['date_received'],
                $x['category'],
                $x['description'],
                $x['estimated_value'],
                $x['gift_from'],
                $x['relationship'],
                $x['purpose'],
                $x['action_taken'],
            ]);
        }
        fclose($out);
        exit;
    }
}






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

    $data['title'] = 'Staff Declaration Settings';

    // roles list
    $data['roles'] = $this->db->get(db_prefix().'roles')->result_array();

    // current saved values
    $data['selected_role_ids']  = array_filter(array_map('intval', explode(',', (string)get_option('sd_notify_role_ids'))));
    $data['selected_staff_ids'] = array_filter(array_map('intval', explode(',', (string)get_option('sd_notify_staff_ids'))));

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

    // pass dynamic urls to view (so view can be reused)
    $data['form_action'] = admin_url('staff_declaration/settings');
    $data['back_url']    = admin_url('staff_declaration');

    if ($this->input->post()) {
        $roleIds  = (array)$this->input->post('role_ids');
        $staffIds = (array)$this->input->post('staff_ids');

        update_option('sd_notify_role_ids', implode(',', $roleIds));
        update_option('sd_notify_staff_ids', implode(',', $staffIds));

        set_alert('success', 'Settings saved');
        redirect(admin_url('staff_declaration/settings'));
    }

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



//Notify HOD && PCEO
private function _notify_hod($id, $submitter_id)
{
    $decl = $this->staff_declaration_model->get($id);
    if (!$decl || empty($decl['decl']['hod_id'])) return;

    $hod = $this->db->select('staffid, email, firstname, lastname')
        ->from(db_prefix().'staff')
        ->where('staffid', (int)$decl['decl']['hod_id'])
        ->where('active', 1)
        ->get()->row_array();

    if (!$hod) return;

    $url = admin_url('staff_declaration/view/'.$id);

    if (function_exists('add_notification')) {
        add_notification([
            'touserid' => (int)$hod['staffid'],
            'link'     => 'staff_declaration/view/'.$id,
            'description' => 'Gift, Hospitality and Entertainment Disclosure pending HOD approval (#'.$id.')',
            'additional_data' => serialize([get_staff_full_name($submitter_id)]),
        ]);
    }

    // Email
    $this->_send_email_to($hod['email'], $decl, $url);

    if (function_exists('pusher_trigger_notification')) {
        pusher_trigger_notification([(int)$hod['staffid']]);
    }
}
public function hod_decide($id)
{
    $id = (int)$id;
    $decl = $this->staff_declaration_model->get($id);
    if (!$decl) show_404();

    $logged = (int)get_staff_user_id();
    $decl =$decl['decl'];
    // Only HOD can decide when pending_hod
    if ($decl['status'] !== 'pending_hod' || (int)$decl['hod_id'] !== $logged) {
        return $this->_deny();
    }

    $action  = $this->input->post('action', true); // 'approved' / 'rejected'
    $comment = $this->input->post('comment', true);

    $prefix = $this->activity_prefix($id);
    $actor_id   = (int)get_staff_user_id();
    $actor_name = get_staff_full_name($actor_id);

    if ($action === 'approved') {
    log_activity($prefix . 'HOD Approved by ' . $actor_name . ($comment ? ' | Comment: ' . $comment : ''), $actor_id);
} else {
    log_activity($prefix . 'HOD Rejected by ' . $actor_name . ($comment ? ' | Comment: ' . $comment : ''), $actor_id);
}

    if (!in_array($action, ['approved','rejected'], true)) {
        set_alert('danger', 'Invalid action.');
        redirect(admin_url('staff_declaration/view/'.$id));
    }

    $this->staff_declaration_model->set_hod_decision($id, $logged, $action, $comment);

    // If approved -> notify final recipients (level 2)
    if ($action === 'approved') {
        $this->_notify_recipients($id, (int)$decl['staff_id']); // your existing settings-based method
    } else {
        // optional: notify submitter that it was rejected
        $this->_notify_submitter($id, (int)$decl['staff_id'], 'rejected by HOD', $comment);
    }

    set_alert('success', 'Decision saved.');
    redirect(admin_url('staff_declaration/view/'.$id));
}
public function final_decide($id)
{
    $id = (int)$id;
    $decl = $this->staff_declaration_model->get($id);
    if (!$decl) show_404();

    if ($decl['decl']['status'] !== 'pending_final') {
        set_alert('warning', 'This request is not pending final approval.');
        redirect(admin_url('staff_declaration/view/'.$id));
    }

    $logged = (int)get_staff_user_id();

    // Must be in recipients list or admin
    $recipients = $this->staff_declaration_model->get_notify_recipients();
    $allowed_ids = array_map('intval', array_column($recipients, 'staffid'));

    if (!is_admin() && !in_array($logged, $allowed_ids, true)) {
        return $this->_deny();
    }

    $action  = $this->input->post('action', true); // approved/rejected
    $comment = $this->input->post('comment', true);
    $prefix = $this->activity_prefix($id);

$actor_id   = (int)get_staff_user_id();
$actor_name = get_staff_full_name($actor_id);
if ($action === 'approved') {
    log_activity($prefix . 'Final Approved by ' . $actor_name . ($comment ? ' | Comment: ' . $comment : ''), $actor_id);
} else {
    log_activity($prefix . 'Final Rejected by ' . $actor_name . ($comment ? ' | Comment: ' . $comment : ''), $actor_id);
}


    if (!in_array($action, ['approved','rejected'], true)) {
        set_alert('danger', 'Invalid action.');
        redirect(admin_url('staff_declaration/view/'.$id));
    }

    $this->staff_declaration_model->set_final_decision($id, $logged, $action, $comment);

    $this->_notify_submitter($id, (int)$decl['decl']['staff_id'], 'final '.$action, $comment);

    set_alert('success', 'Final decision saved.');
    redirect(admin_url('staff_declaration/view/'.$id));
}
private function _notify_recipients($id, $submitter_id)
  {
    $decl = $this->staff_declaration_model->get($id);
    $recipients = $this->staff_declaration_model->get_notify_recipients();
    if (empty($recipients)) return;

    $url = admin_url('staff_declaration/view/'.$id);

    foreach ($recipients as $u) {
      // in-app notification
      if (function_exists('add_notification')) {
        add_notification([
          'touserid' => (int)$u['staffid'],
          'link'     => 'staff_declaration/view/'.$id,
          'description' => 'New Gift, Hospitality and Entertainment Disclosure submitted (#'.$id.')',
          'additional_data' => serialize([get_staff_full_name($submitter_id)]),
        ]);
      }

      // email (same style you already use)
      $this->_send_email_to($u['email'], $decl, $url);
    }

    if (function_exists('pusher_trigger_notification')) {
      pusher_trigger_notification(array_column($recipients, 'staffid'));
    }
  }
  private function _send_email_to($toEmail, $decl, $url)
  {
    if (empty($toEmail)) return;

    $subject = 'Approval Needed: New Gift, Hospitality and Entertainment Disclosure';
    $message =
      '<p>A new Conflict of Interest Disclosure Request has been submitted for your review and approval.</p>'
      .'<p><strong>Name:</strong> '.htmlspecialchars($decl['decl']['staff_name'] ?? '').'<br>'
      .'<strong>Staff ID:</strong> '.htmlspecialchars($decl['decl']['staff_code'] ?? '').'<br>'
      .'<strong>Department:</strong> '.htmlspecialchars($decl['decl']['department'] ?? '').'<br>'
      .'<strong>Date:</strong> '.htmlspecialchars($decl['decl']['created_at'] ?? '').'<br>'
      .'</p>'
      .'<p>View: <a href="'.$url.'">'.$url.'</a></p>';

    if (function_exists('send_mail')) {
      @send_mail($toEmail, $subject, $message);
      return;
    }

    $CI = &get_instance();
    $CI->load->library('email');
    $CI->email->clear(true);
$fromEmail = 'humancapital@inceif.edu.my';
$fromName  = 'Human Capital INCEIF';
$CI->email->from($fromEmail, $fromName);
$CI->email->reply_to($fromEmail, $fromName);
    $CI->email->to($toEmail);
    $CI->email->subject($subject);
    $CI->email->message($message);
    @$CI->email->send();
  }

/**
 * Notify the submitter when a decision is made.
 *
 * @param int    $id            engagement request id
 * @param int    $submitter_id  staff_id of submitter
 * @param string $stage_action  e.g. "hod approved", "final rejected"
 * @param string|null $comment  approver comment
 */
private function _notify_submitter($id, $submitter_id, $stage_action, $comment = null)
{
    $id          = (int)$id;
    $submitter_id = (int)$submitter_id;

    // get submitter info
    $submitter = $this->db->select('staffid,email,firstname,lastname')
        ->from(db_prefix().'staff')
        ->where('staffid', $submitter_id)
        ->limit(1)
        ->get()
        ->row_array();

    if (!$submitter) {
        return;
    }

    $url  = admin_url('staff_declaration/view/'.$id);
    $name = trim(($submitter['firstname'] ?? '').' '.($submitter['lastname'] ?? '')) ?: ('Staff #'.$submitter_id);

    // ---- In-app notification ----
    if (function_exists('add_notification')) {
        add_notification([
            'touserid'        => (int)$submitter['staffid'],
            'link'            => 'staff_declaration/view/'.$id,
            'description'     => 'Your Gift, Hospitality and Entertainment Disclosure submission has been '.$stage_action.' (#'.$id.')',
            'additional_data' => serialize([$name]),
        ]);
    }

    // ---- Email ----
    $subject = 'Gift, Hospitality and Entertainment Disclosure: '.$stage_action.' (#'.$id.')';

    $commentTxt = '';
    $comment = trim((string)$comment);
    if ($comment !== '') {
        $commentTxt = '<p><strong>Comment:</strong><br>'.nl2br(htmlspecialchars($comment)).'</p>';
    }

    $message = '
        <p>Dear '.htmlspecialchars($name).',</p>
        <p>Your Gift, Hospitality and Entertainment Disclosure submission <strong>#'.$id.'</strong> has been <strong>'.htmlspecialchars($stage_action).'</strong>.</p>
        '.$commentTxt.'
        <p>You may view the record here:</p>
        <p><a href="'.htmlspecialchars($url).'">'.htmlspecialchars($url).'</a></p>
        <br>
        <p>Thank you.</p>
    ';

    //$this->_send_email_to($submitter['email'], $subject, $message);

    // ---- Real-time bell notification ----
    if (function_exists('pusher_trigger_notification')) {
        pusher_trigger_notification([(int)$submitter['staffid']]);
    }
}



}
