<?php

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

/**
 * @property Tickets_model $tickets_model
 */
class Tickets extends AdminController
{
    public function __construct()
    {
        parent::__construct();
        if (get_option('access_tickets_to_none_staff_members') == 0 && ! is_staff_member()) {
            redirect(admin_url());
        }
        $this->load->model('tickets_model');
    }

    public function index($status = '', $userid = '')
    {
        close_setup_menu();

        if (! is_numeric($status)) {
            $status = '';
        }

        $data['table'] = App_table::find('tickets');

        if ($this->input->is_ajax_request()) {
            if (! $this->input->post('via_ticket')) {
                $tableParams = [
                    'status' => $status,
                    'userid' => $userid,
                ];
            } else {
                // request for othes tickets when single ticket is opened
                $tableParams = [
                    'userid'     => $this->input->post('via_ticket_userid'),
                    'via_ticket' => $this->input->post('via_ticket'),
                ];

                if ($tableParams['userid'] == 0) {
                    unset($tableParams['userid']);
                    $tableParams['by_email'] = $this->input->post('via_ticket_email');
                }
            }
            $data['table']->output($tableParams);
        }

        $data['chosen_ticket_status']              = $status;
        $data['weekly_tickets_opening_statistics'] = json_encode($this->tickets_model->get_weekly_tickets_opening_statistics());
        $data['title']                             = _l('support_tickets');
        $this->load->model('departments_model');
        $data['statuses']             = $this->tickets_model->get_ticket_status();
        $data['staff_deparments_ids'] = $this->departments_model->get_staff_departments(get_staff_user_id(), true);
        $data['departments']          = $this->departments_model->get();
        $data['priorities']           = $this->tickets_model->get_priority();
        $data['services']             = $this->tickets_model->get_service();
        $data['ticket_assignees']     = $this->tickets_model->get_tickets_assignes_disctinct();
        $data['bodyclass']            = 'tickets-page';
        add_admin_tickets_js_assets();
        $data['default_tickets_list_statuses'] = hooks()->apply_filters('default_tickets_list_statuses', [1, 2, 4]);
        $this->load->view('admin/tickets/list', $data);
    }
    
    public function add($userid = false)
{
    // ---------------------------
    // 1) HANDLE POST (CREATE)
    // ---------------------------
    if ($this->input->post()) {

        $staff_id = (int)get_staff_user_id();

        $post = $this->input->post();
        $post['created_by'] = $staff_id;

        // rich editor
        $post['message'] = html_purify($this->input->post('message', false));

        // ✅ Determine year (based on posted date or now)
        $year = (int)date('Y');

        // ✅ HOD logic
        $notify_hod = (int)($post['notify_hod'] ?? 0);

        if ($notify_hod === 1) {
            $hod_id = (int)$this->tickets_model->get_staff_hod($staff_id);
            $post['hod_id']     = $hod_id;
            $post['hod_status'] = 'pending';
            $post['status']     = 6;
        } else {
            $post['hod_id']     = 0;
            $post['hod_status'] = null;
            $post['status']     = 1;
        }

        // ✅ TRANSACTION to protect ref uniqueness
        $this->db->trans_begin();

        try {
            // Lock year rows
            $this->db->query(
                'SELECT ref_seq FROM ' . db_prefix() . 'tickets WHERE ref_year = ' . $year . ' FOR UPDATE'
            );

            // Generate next ref (move this method into tickets_model)
            $refData = $this->tickets_model->generate_ticket_ref($year);

            $post['ref_year'] = $refData['ref_year'];
            $post['ref_seq']  = $refData['ref_seq'];
            $post['ref']      = $refData['ref'];

            // Create ticket
            $id = $this->tickets_model->add($post, $staff_id);

            if (!$id) {
                throw new Exception('Ticket insert failed');
            }

            $this->db->trans_commit();

            set_alert('success', _l('new_ticket_added_successfully', $post['ref'] ));
            redirect(admin_url('tickets/ticket/' . $id));

        } catch (Throwable $e) {
            $this->db->trans_rollback();
            log_message('error', '[Tickets::add] Failed: ' . $e->getMessage());
            set_alert('danger', 'Failed to create ticket. Please try again.');
            redirect(admin_url('tickets/add'));
        }
    }

    // ---------------------------
    // 2) GET VIEW (FORM)
    // ---------------------------
    if ($userid !== false) {
        $data['userid'] = $userid;
        $data['client'] = $this->clients_model->get($userid);
    }

    $this->load->model('knowledge_base_model');
    $this->load->model('departments_model');

    $staff_id    = (int)get_staff_user_id();
    $staff_depts = $this->departments_model->get_staff_departments($staff_id);
    $staff       = $this->staff_model->get($staff_id);

    $data['departments'] = $this->departments_model->get();

    $map = [];
    foreach ((array)$data['departments'] as $d) {
        $map[(int)$d['departmentid']] = $d['name'];
    }

    $names = [];
    foreach ((array)$staff_depts as $sd) {
        $did = (int)$sd['departmentid'];
        if (isset($map[$did])) {
            $names[] = $map[$did];
        }
    }

    $data['prefill_staff_id']      = $staff_id;
    $data['prefill_staff_name']    = trim($staff->firstname . ' ' . $staff->lastname);
    $data['prefill_staff_email']   = $staff->email;
    $data['department_display']    = implode(', ', $names);
    $data['prefill_department_id'] = !empty($staff_depts) ? (int)$staff_depts[0]['departmentid'] : '';

    $data['staff_code']     = get_staff_inceif_staff_id($staff_id) ?: (string)$staff_id;
    $data['staff_position'] = get_staff_position($staff_id);

    $data['predefined_replies'] = $this->tickets_model->get_predefined_reply();
    $data['priorities']         = $this->tickets_model->get_priority();
    $data['services']           = $this->tickets_model->get_service();

    $whereStaff = ['active' => 1];
    if (get_option('access_tickets_to_none_staff_members') == 0) {
        $whereStaff['is_not_staff'] = 0;
    }
    $data['staff']     = $this->staff_model->get('', $whereStaff);
    $data['articles']  = $this->knowledge_base_model->get();
    $data['bodyclass'] = 'ticket';
    $data['title']     = _l('new_ticket');

    // Keep your existing project/contact logic
    if ($this->input->get('project_id') && $this->input->get('project_id') > 0) {
        $data['project_id'] = $this->input->get('project_id');
        $data['userid']     = get_client_id_by_project_id($data['project_id']);
        if (total_rows(db_prefix().'contacts', ['active'=>1,'userid'=>$data['userid']]) == 1) {
            $contact = $this->clients_model->get_contacts($data['userid']);
            if (isset($contact[0])) $data['contact'] = $contact[0];
        }
    } elseif ($this->input->get('contact_id') && $this->input->get('contact_id') > 0 && $this->input->get('userid')) {
        $contact_id = $this->input->get('contact_id');
        if (total_rows(db_prefix().'contacts', ['active'=>1,'id'=>$contact_id]) == 1) {
            $contact = $this->clients_model->get_contact($contact_id);
            if ($contact) $data['contact'] = (array)$contact;
        }
    }

    add_admin_tickets_js_assets();
    $this->load->view('admin/tickets/add', $data);
}

    public function add__OLD($userid = false)
    {
        if ($this->input->post()) {
            $staff_id = get_staff_user_id();
            $data            = $this->input->post();
            $data['created_by'] = (int)$staff_id;
            $data['message'] = html_purify($this->input->post('message', false));
              // ✅ If Yes selected, set hod_id into ticket payload
        $notify_hod = (int)($data['notify_hod'] ?? 0);
        
$year = !empty($data['date']) ? (int)date('Y', strtotime($data['date'])) : (int)date('Y');

// IMPORTANT: lock rows for that year so 2 users don’t get same ref
$this->db->query('SELECT ref_seq FROM '.db_prefix().'tickets WHERE ref_year = '.$year.' FOR UPDATE');

$refData = $this->generate_ticket_ref($year);

// add into insert payload
$data['ref_year'] = $refData['ref_year'];
$data['ref_seq']  = $refData['ref_seq'];
$data['ref']      = $refData['ref'];

        if ($notify_hod === 1) {
            $hod_id = (int)$this->tickets_model->get_staff_hod($staff_id);
            $data['hod_id'] = $hod_id; 
            $data['hod_status'] = 'pending'; 
            $data['status'] = 6;
        } else {
            $data['hod_id'] = 0; // optional, keep clean
            $data['hod_status'] = null; // or 'na'
            $data['status'] = 1;
        }
            $id              = $this->tickets_model->add($data, get_staff_user_id());            
            if ($id) {
                set_alert('success', _l('new_ticket_added_successfully', $id));
                redirect(admin_url('tickets/ticket/' . $id));
            }
        }
        if ($userid !== false) {
            $data['userid'] = $userid;
            $data['client'] = $this->clients_model->get($userid);
        }
        // Load necessary models
        $this->load->model('knowledge_base_model');
        $this->load->model('departments_model');

        $staff_id = get_staff_user_id();
        $staff_depts = $this->departments_model->get_staff_departments($staff_id);
        $staff = $this->staff_model->get($staff_id);

        $data['departments']        = $this->departments_model->get();

        $map = [];
        foreach ((array) $data['departments'] 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['prefill_staff_id']        = $staff_id;
        $data['prefill_staff_name']      = trim($staff->firstname . ' ' . $staff->lastname);
        $data['prefill_staff_email']     = $staff->email;
        $data['department_display']      = implode(', ', $names);

        // optional: keep a “primary” department id (first one) if you still need departmentid internally
        $data['prefill_department_id']   = !empty($staff_depts) ? (int)$staff_depts[0]['departmentid'] : '';

        $data['staff_code']              = get_staff_inceif_staff_id($staff_id) ?: (string)$staff_id;
        $data['staff_position']          = get_staff_position($staff_id);

        $data['predefined_replies'] = $this->tickets_model->get_predefined_reply();
        $data['priorities']         = $this->tickets_model->get_priority();
        $data['services']           = $this->tickets_model->get_service();
        $whereStaff                 = ['active' => 1];
        if (get_option('access_tickets_to_none_staff_members') == 0) {
            $whereStaff['is_not_staff'] = 0;
        }
        $data['staff']     = $this->staff_model->get('', $whereStaff);
        $data['articles']  = $this->knowledge_base_model->get();
        $data['bodyclass'] = 'ticket';
        $data['title']     = _l('new_ticket');

        if ($this->input->get('project_id') && $this->input->get('project_id') > 0) {
            // request from project area to create new ticket
            $data['project_id'] = $this->input->get('project_id');
            $data['userid']     = get_client_id_by_project_id($data['project_id']);
            if (total_rows(db_prefix() . 'contacts', ['active' => 1, 'userid' => $data['userid']]) == 1) {
                $contact = $this->clients_model->get_contacts($data['userid']);
                if (isset($contact[0])) {
                    $data['contact'] = $contact[0];
                }
            }
        } elseif ($this->input->get('contact_id') && $this->input->get('contact_id') > 0 && $this->input->get('userid')) {
            $contact_id = $this->input->get('contact_id');
            if (total_rows(db_prefix() . 'contacts', ['active' => 1, 'id' => $contact_id]) == 1) {
                $contact = $this->clients_model->get_contact($contact_id);
                if ($contact) {
                    $data['contact'] = (array) $contact;
                }
            }
        }
        add_admin_tickets_js_assets();
        $this->load->view('admin/tickets/add', $data);
    }

    public function delete($ticketid)
    {
        if (! $ticketid) {
            redirect(admin_url('tickets'));
        }

        if (! can_staff_delete_ticket()) {
            access_denied('delete ticket');
        }

        $response = $this->tickets_model->delete($ticketid);

        if ($response == true) {
            set_alert('success', _l('deleted', _l('ticket')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('ticket_lowercase')));
        }

        // ensure if deleted from single ticket page, user is redirected to index
        if (str_contains(previous_url(), 'ticket/' . $ticketid)) {
            redirect(admin_url('tickets'));

            return;
        }
        redirect(previous_url() ?: $_SERVER['HTTP_REFERER']);
    }

    public function delete_attachment($id)
    {
        if (is_admin() || (! is_admin() && get_option('allow_non_admin_staff_to_delete_ticket_attachments') == '1')) {
            if (get_option('staff_access_only_assigned_departments') == 1 && ! is_admin()) {
                $attachment = $this->tickets_model->get_ticket_attachment($id);
                $ticket     = $this->tickets_model->get_ticket_by_id($attachment->ticketid);

                $this->load->model('departments_model');
                $staff_departments = $this->departments_model->get_staff_departments(get_staff_user_id(), true);
                if (! in_array($ticket->department, $staff_departments)) {
                    set_alert('danger', _l('ticket_access_by_department_denied'));
                    redirect(admin_url('access_denied'));
                }
            }

            $this->tickets_model->delete_ticket_attachment($id);
        }

        redirect(previous_url() ?: $_SERVER['HTTP_REFERER']);
    }

    public function update_staff_replying($ticketId, $userId = '')
    {
        if ($this->input->is_ajax_request()) {
            echo json_encode(['success' => $this->tickets_model->update_staff_replying($ticketId, $userId)]);

            exit;
        }
    }

    public function check_staff_replying($ticketId)
    {
        if ($this->input->is_ajax_request()) {
            $ticket            = $this->tickets_model->get_staff_replying($ticketId);
            $isAnotherReplying = $ticket->staff_id_replying !== null && $ticket->staff_id_replying !== get_staff_user_id();
            echo json_encode([
                'is_other_staff_replying' => $isAnotherReplying,
                'message'                 => $isAnotherReplying ? e(_l('staff_is_currently_replying', get_staff_full_name($ticket->staff_id_replying))) : '',
            ]);

            exit;
        }
    }



public function ticket($id)
{
    if (! $id) {
        redirect(admin_url('tickets/add'));
    }

    $staff_id = get_staff_user_id();
    $ticket = $this->tickets_model->get_ticket_by_id($id);
if (!$ticket) {
    blank_page(_l('ticket_not_found'));
}

// Permissions
    $can_view_global = has_permission('tickets', '', 'view');
    $can_view_own    = has_permission('tickets', '', 'view_own');

    $isOwner = ((int)($ticket->created_by ?? 0) === $staff_id);
    $isHod   = ((int)($ticket->hod_id ?? 0) === $staff_id);

    if (!is_admin() && !$can_view_own) {
        // if no global view, must be own + owner/hod
        if ( (!$isOwner && !$isHod)) {
            access_denied('tickets');
        }
    }

// ticket owner (staff who created)
$owner_staff_id = (int)($ticket->created_by ?? 0);

// fallback: if created_by not set (older tickets), use current staff
if ($owner_staff_id <= 0) {
    $owner_staff_id = (int)get_staff_user_id();
}



// staff row (owner)
$this->load->model('staff_model');
$staff = $this->staff_model->get($owner_staff_id);

// departments display
$this->load->model('departments_model');
$staff_depts = $this->departments_model->get_staff_departments($owner_staff_id, false);
$all_depts   = $this->departments_model->get();

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

$names = [];
foreach ((array)$staff_depts as $sd) {
    $did = (int)$sd['departmentid'];
    if (isset($map[$did])) $names[] = $map[$did];
}

$data['prefill_staff_id']       = $owner_staff_id;
$data['prefill_staff_name']     = $staff ? trim($staff->firstname . ' ' . $staff->lastname) : '';
$data['prefill_staff_email']    = $staff ? $staff->email : '';
$data['prefill_department_id']  = !empty($staff_depts) ? (int)$staff_depts[0]['departmentid'] : '';
$data['department_display']     = implode(', ', $names);

$data['staff_code']             = get_staff_inceif_staff_id($owner_staff_id) ?: (string)$owner_staff_id;
$data['staff_position']         = get_staff_position($owner_staff_id);

// keep ticket in data too



    // Load ticket first
   
    if (! $ticket) {
        blank_page(_l('ticket_not_found'));
    }

    // View permissions
    $can_view_global = has_permission('tickets', '', 'view');      // View(Global)
    $can_view_own    = has_permission('tickets', '', 'view_own');  // View(Own)

    $is_own = ((int)$ticket->created_by === (int)$staff_id) || ((int)$ticket->hod_id === (int)$staff_id);

    if (!$can_view_global && !($can_view_own && $is_own)) {
        access_denied('tickets');
    }

    // Department restriction (keep this AFTER permission check or BEFORE - both OK)
    if (get_option('staff_access_only_assigned_departments') == 1) {
        if (! is_admin()) {
            $this->load->model('departments_model');
            $staff_departments = $this->departments_model->get_staff_departments($staff_id, true);

            if (! in_array($ticket->department, $staff_departments)) {
                set_alert('danger', _l('ticket_access_by_department_denied'));
                redirect(admin_url('access_denied'));
            }
        }
    }

    // Prepare view data
    $data['ticket']         = $ticket;
    $data['merged_tickets'] = $this->tickets_model->get_merged_tickets_by_primary_id($id);

    // If reply is submitted
    if ($this->input->post()) {

        // EDIT permissions (Reply counts as edit/action)
        $can_edit_global = has_permission('tickets', '', 'edit');      // Edit(Global)
        $can_edit_own    = has_permission('tickets', '', 'edit_own');  // Edit(Own)

        if (!$can_edit_global && !($can_edit_own && $is_own)) {
            access_denied('tickets');
        }

        $returnToTicketList = false;
        $post               = $this->input->post();

        if (!is_admin() && !has_permission('tickets', '', 'edit')) {
    $post['status'] = $ticket->status;
    
}

        if (isset($post['ticket_add_response_and_back_to_list'])) {
            $returnToTicketList = true;
            unset($post['ticket_add_response_and_back_to_list']);
        }

        $post['message'] = html_purify($this->input->post('message', false));

        $replyid = $this->tickets_model->add_reply($post, $id, $staff_id);

        if ($replyid) {
            set_alert('success', _l('replied_to_ticket_successfully', $id));
        }

        if (! $returnToTicketList) {
            redirect(admin_url('tickets/ticket/' . $id));
        } else {
            set_ticket_open(0, $id);
            redirect(admin_url('tickets'));
        }
    }

    // Load necessary models
    $this->load->model('knowledge_base_model');
    $this->load->model('departments_model');

    $data['statuses']                       = $this->tickets_model->get_ticket_status();
    $data['statuses']['callback_translate'] = 'ticket_status_translate';

    $data['departments']        = $this->departments_model->get();
    $data['predefined_replies'] = $this->tickets_model->get_predefined_reply();
    $data['priorities']         = $this->tickets_model->get_priority();
    $data['services']           = $this->tickets_model->get_service();

    $whereStaff = ['active' => 1];
    if (get_option('access_tickets_to_none_staff_members') == 0) {
        $whereStaff['is_not_staff'] = 0;
    }

    $data['staff']          = $this->staff_model->get('', $whereStaff);
    $data['articles']       = $this->knowledge_base_model->get();
    $data['ticket_replies'] = $this->tickets_model->get_ticket_replies($id);

    $data['bodyclass']      = 'top-tabs ticket single-ticket';
    $data['title']          = $data['ticket']->subject;

    $data['sender_blocked'] = total_rows(db_prefix() . 'spam_filters', [
        'type' => 'sender',
        'value' => $data['ticket']->ticket_email,
        'rel_type' => 'tickets',
    ]) > 0;

    $data['ticket']->ticket_notes = $this->misc_model->get_notes($id, 'ticket');

    add_admin_tickets_js_assets();
    $this->load->view('admin/tickets/single', $data);
}



public function hod_decide($ticketId)
{
    $ticketId = (int)$ticketId;

    $ticket = $this->tickets_model->get($ticketId); // adjust if your get() signature differs
    if (!$ticket) {
        show_404();
    }

    $logged = (int)get_staff_user_id();
    $isHod  = ((int)($ticket->hod_id ?? 0) === $logged);
    $created_by = (int)($ticket->created_by);

    if (!$isHod && !is_admin()) {
        access_denied('tickets');
    }

 $hs = $ticket->hod_status ?? '';

if (!in_array($hs, ['pending', 'rejected'], true)) {
    set_alert('warning', 'Already decided.');
    redirect(admin_url('tickets/ticket/' . $ticketId));
}

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

    $action = ($action === 'acknowledged') ? 'acknowledged' : 'rejected';

    $update = [     
        'hod_status'  => $action,
        'hod_comment' => $comment ?: null,    
        'hod_date'    => date('Y-m-d H:i:s'),
        'updated_at'  => date('Y-m-d H:i:s'),
    ];

// ✅ set ticket status based on HOD decision
if ($action === 'rejected') {
    $update['status'] = 7; // rejected status id
} else {
    $update['status'] = 1; // approved/open/whatever you want after acknowledge
}



     $this->db->where('ticketid', $ticketId);
     $this->db->update(db_prefix().'tickets', $update);

    $post['message'] = 'Incident Report #' . $ticketId . ' HOD ' . strtoupper($action) . ' by ' . get_staff_full_name($logged) . ($comment ? (' - '.$comment) : '');
    $post['ticketid'] = $ticketId;
    $post['admin'] = $logged;

    //$replyid = $this->tickets_model->add_reply($post, $ticketId, $logged);
    $this->db->insert(db_prefix() . 'ticket_replies', $post);
    $replyid = $this->db->insert_id();

    // log_activity('Ticket #' . $ticketId . ' HOD ' . strtoupper($action) . ' by ' . get_staff_full_name($logged) . ($comment ? (' - '.$comment) : ''), $logged);

       if ($replyid) {
            set_alert('success', _l('hod_success', $ticketId));
        }
        if ($action === 'rejected') {
        send_mail_template(
                'hod_rejected_to_staff',              
                get_staff($created_by)->email,
                $created_by,
                $ticketId,             
                
            );
    }

    //set_alert('success', 'Saved.');
    redirect(admin_url('tickets/ticket/' . $ticketId));
}

    public function ticket__OLD($id)
    {
        if (! $id) {
            redirect(admin_url('tickets/add'));
        }

        $data['ticket']         = $this->tickets_model->get_ticket_by_id($id);
        $data['merged_tickets'] = $this->tickets_model->get_merged_tickets_by_primary_id($id);

        if (! $data['ticket']) {
            blank_page(_l('ticket_not_found'));
        }

        if (get_option('staff_access_only_assigned_departments') == 1) {
            if (! is_admin()) {
                $this->load->model('departments_model');
                $staff_departments = $this->departments_model->get_staff_departments(get_staff_user_id(), true);
                if (! in_array($data['ticket']->department, $staff_departments)) {
                    set_alert('danger', _l('ticket_access_by_department_denied'));
                    redirect(admin_url('access_denied'));
                }
            }
        }

        if ($this->input->post()) {
            $returnToTicketList = false;
            $data               = $this->input->post();

            if (isset($data['ticket_add_response_and_back_to_list'])) {
                $returnToTicketList = true;
                unset($data['ticket_add_response_and_back_to_list']);
            }

            $data['message'] = html_purify($this->input->post('message', false));
            $replyid         = $this->tickets_model->add_reply($data, $id, get_staff_user_id());

            if ($replyid) {
                set_alert('success', _l('replied_to_ticket_successfully', $id));
            }
            if (! $returnToTicketList) {
                redirect(admin_url('tickets/ticket/' . $id));
            } else {
                set_ticket_open(0, $id);
                redirect(admin_url('tickets'));
            }
        }
        // Load necessary models
        $this->load->model('knowledge_base_model');
        $this->load->model('departments_model');

        $data['statuses']                       = $this->tickets_model->get_ticket_status();
        $data['statuses']['callback_translate'] = 'ticket_status_translate';

        $data['departments']        = $this->departments_model->get();
        $data['predefined_replies'] = $this->tickets_model->get_predefined_reply();
        $data['priorities']         = $this->tickets_model->get_priority();
        $data['services']           = $this->tickets_model->get_service();
        $whereStaff                 = ['active' => 1];
        if (get_option('access_tickets_to_none_staff_members') == 0) {
            $whereStaff['is_not_staff'] = 0;
        }
        $data['staff']          = $this->staff_model->get('', $whereStaff);
        $data['articles']       = $this->knowledge_base_model->get();
        $data['ticket_replies'] = $this->tickets_model->get_ticket_replies($id);
        $data['bodyclass']      = 'top-tabs ticket single-ticket';
        $data['title']          = $data['ticket']->subject;
        $data['sender_blocked'] = total_rows(db_prefix() . 'spam_filters', [
            'type' => 'sender', 'value' => $data['ticket']->ticket_email, 'rel_type' => 'tickets',
        ]) > 0;
        $data['ticket']->ticket_notes = $this->misc_model->get_notes($id, 'ticket');
        add_admin_tickets_js_assets();
        $this->load->view('admin/tickets/single', $data);
    }



public function edit_message()
{

    if (!$this->input->post()) {
        redirect(admin_url('tickets'));
    }

    $staff_id    = get_staff_user_id();
    $type        = $this->input->post('type'); // 'ticket' or 'reply'
    $id          = (int)$this->input->post('id');
    $main_ticket = (int)$this->input->post('main_ticket');

    // Load main ticket for permission checks (owner/HOD)
    $ticket = $this->tickets_model->get_ticket_by_id($main_ticket);
    if (!$ticket) {
        blank_page(_l('ticket_not_found'));
    }

    // -----------------------------
    // Permission checks (NEW RULES)
    // -----------------------------
    $can_edit_global = has_permission('tickets', '', 'edit');      // Edit(Global)
    $can_edit_own    = has_permission('tickets', '', 'edit_own');  // Edit(Own)

    $is_own = ((int)$ticket->created_by === (int)$staff_id) || ((int)$ticket->hod_id === (int)$staff_id);

    if (!$can_edit_global && !($can_edit_own && $is_own)) {
        access_denied('tickets');
    }

    // Optional: keep Perfex department restriction too (consistent with view)
    if (get_option('staff_access_only_assigned_departments') == 1 && !is_admin()) {
        $this->load->model('departments_model');
        $staff_departments = $this->departments_model->get_staff_departments($staff_id, true);
        if (!in_array((int)$ticket->department, $staff_departments)) {
            access_denied('tickets');
        }
    }

    // Sanitize HTML content
    $data_html = html_purify($this->input->post('data', false));

    // Update message
    if ($type === 'reply') {
        // (Recommended) ensure the reply belongs to this ticket
        $reply = $this->db->select('id,ticketid')
            ->from(db_prefix() . 'ticket_replies')
            ->where('id', $id)
            ->get()->row();

        if (!$reply || (int)$reply->ticketid !== $main_ticket) {
            access_denied('tickets');
        }

        $this->db->where('id', $id);
        $this->db->update(db_prefix() . 'ticket_replies', ['message' => $data_html]);

    } elseif ($type === 'ticket') {

        if ($id !== $main_ticket) {
            access_denied('tickets');
        }

        $this->db->where('ticketid', $id);
        $this->db->update(db_prefix() . 'tickets', ['message' => $data_html]);

    } else {
        access_denied('tickets');
    }

    if ($this->db->affected_rows() > 0) {
        set_alert('success', _l('ticket_message_updated_successfully'));
    }

    redirect(admin_url('tickets/ticket/' . $main_ticket));
}

public function ajax_edit_message()
{
    if ($this->input->post()) {

        // your NEW permission check (Edit Global / Edit Own) should already be here

        $data         = $this->input->post();
        $data['data'] = html_purify($this->input->post('data', false));

       if ($data['type'] == 'ticket') {
            $this->db->where('ticketid', (int)$data['id']);
            $this->db->update(db_prefix().'tickets', ['message' => $data['data']]);
        }

        $ok = $this->db->affected_rows() > 0;

        // ✅ if AJAX, return JSON instead of redirect
        if ($this->input->is_ajax_request()) {
            echo json_encode(['success' => true, 'updated' => $ok]);
            exit();
        }

        if ($ok) {
            set_alert('success', _l('ticket_message_updated_successfully'));
        }
        redirect(admin_url('tickets/ticket/' . (int)$data['main_ticket']));
    }
}


    public function delete_ticket_reply($ticket_id, $reply_id)
    {
        if (! $reply_id) {
            redirect(admin_url('tickets'));
        }

        if (! can_staff_delete_ticket_reply()) {
            access_denied('delete ticket');
        }

        $response = $this->tickets_model->delete_ticket_reply($ticket_id, $reply_id);
        if ($response == true) {
            set_alert('success', _l('deleted', _l('ticket_reply')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('ticket_reply')));
        }
        redirect(admin_url('tickets/ticket/' . $ticket_id));
    }

    public function change_status_ajax($id, $status)
{
    if (!$this->input->is_ajax_request()) {
        show_404();
    }

    $id     = (int)$id;
    $status = (int)$status;

    $staff_id = (int)get_staff_user_id();

    $can_edit_global = has_permission('tickets', '', 'edit');
    //$can_edit_own    = has_permission('tickets', '', 'edit_own');

    $ticket = $this->tickets_model->get_ticket_by_id($id);
    if (!$ticket) {
        echo json_encode(['error' => true, 'message' => 'Ticket not found']);
        exit;
    }

    $isOwner = ((int)($ticket->created_by ?? 0) === $staff_id);
    $isHod   = ((int)($ticket->hod_id ?? 0) === $staff_id);

    $allowed = is_admin() || $can_edit_global;

    if (!$allowed) {
        echo json_encode(['alert' => 'warning', 'message' => 'Access denied']);
        exit;
    }

    $res = $this->tickets_model->change_ticket_status($id, $status);

    echo json_encode($res);
    exit;
}


    public function change_status_ajax_OLD($id, $status)
    {
        if ($this->input->is_ajax_request()) {
            echo json_encode($this->tickets_model->change_ticket_status($id, $status));
        }
    }

    public function update_single_ticket_settings()
    {
      
        if ($this->input->post()) {    



            if ($this->input->post('merge_ticket_ids') !== 0) {
                $ticketsToMerge = explode(',', $this->input->post('merge_ticket_ids') ?: '');

                $alreadyMergedTickets = $this->tickets_model->get_already_merged_tickets($ticketsToMerge);
                if (count($alreadyMergedTickets) > 0) {
                    echo json_encode([
                        'success' => false,
                        'message' => _l('cannot_merge_tickets_with_ids', implode(',', $alreadyMergedTickets)),
                    ]);

                    exit();
                }
            }


            $success = $this->tickets_model->update_single_ticket_settings($this->input->post());
            if ($success) {
                if (get_option('staff_access_only_assigned_departments') == 1) {
                    $ticket = $this->tickets_model->get_ticket_by_id($this->input->post('ticketid'));
                    $this->load->model('departments_model');
                    $staff_departments = $this->departments_model->get_staff_departments(get_staff_user_id(), true);
                    if (! in_array($ticket->department, $staff_departments) && ! is_admin()) {
                        set_alert('success', _l('ticket_settings_updated_successfully_and_reassigned', $ticket->department_name));
                        echo json_encode([
                            'success'               => $success,
                            'department_reassigned' => true,
                        ]);

                        exit();
                    }
                }
                set_alert('success', _l('ticket_settings_updated_successfully'));
            }
            echo json_encode([
                'success' => $success,
            ]);

            exit();
        }
    }

    // Priorities
    // Get all ticket priorities
    public function priorities()
    {
        if (! is_admin()) {
            access_denied('Ticket Priorities');
        }
        $data['priorities'] = $this->tickets_model->get_priority();
        $data['title']      = _l('ticket_priorities');
        $this->load->view('admin/tickets/priorities/manage', $data);
    }

    // Add new priority od update existing
    public function priority()
    {
        if (! is_admin()) {
            access_denied('Ticket Priorities');
        }
        if ($this->input->post()) {
            if (! $this->input->post('id')) {
                $id = $this->tickets_model->add_priority($this->input->post());
                if ($id) {
                    set_alert('success', _l('added_successfully', _l('ticket_priority')));
                }
            } else {
                $data = $this->input->post();
                $id   = $data['id'];
                unset($data['id']);
                $success = $this->tickets_model->update_priority($data, $id);
                if ($success) {
                    set_alert('success', _l('updated_successfully', _l('ticket_priority')));
                }
            }

            exit;
        }
    }

    // Delete ticket priority
    public function delete_priority($id)
    {
        if (! is_admin()) {
            access_denied('Ticket Priorities');
        }
        if (! $id) {
            redirect(admin_url('tickets/priorities'));
        }
        $response = $this->tickets_model->delete_priority($id);
        if (is_array($response) && isset($response['referenced'])) {
            set_alert('warning', _l('is_referenced', _l('ticket_priority_lowercase')));
        } elseif ($response == true) {
            set_alert('success', _l('deleted', _l('ticket_priority')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('ticket_priority_lowercase')));
        }
        redirect(admin_url('tickets/priorities'));
    }

    // List all ticket predefined replies
    public function predefined_replies()
    {
        if (! is_admin()) {
            access_denied('Predefined Replies');
        }
        if ($this->input->is_ajax_request()) {
            $aColumns = [
                'name',
            ];
            $sIndexColumn = 'id';
            $sTable       = db_prefix() . 'tickets_predefined_replies';
            $result       = data_tables_init($aColumns, $sIndexColumn, $sTable, [], [], [
                'id',
            ]);
            $output  = $result['output'];
            $rResult = $result['rResult'];

            foreach ($rResult as $aRow) {
                $row = [];

                for ($i = 0; $i < count($aColumns); $i++) {
                    $_data = $aRow[$aColumns[$i]];
                    if ($aColumns[$i] == 'name') {
                        $_data = '<a href="' . admin_url('tickets/predefined_reply/' . $aRow['id']) . '" class="tw-font-medium">' . e($_data) . '</a>';
                    }
                    $row[] = $_data;
                }

                $options = '<div class="tw-flex tw-items-center tw-space-x-2">';
                $options .= '<a href="' . admin_url('tickets/predefined_reply/' . $aRow['id']) . '" class="tw-text-neutral-500 hover:tw-text-neutral-700 focus:tw-text-neutral-700">
                    <i class="fa-regular fa-pen-to-square fa-lg"></i>
                </a>';

                $options .= '<a href="' . admin_url('tickets/delete_predefined_reply/' . $aRow['id']) . '"
                class="tw-text-neutral-500 hover:tw-text-neutral-700 focus:tw-text-neutral-700 _delete">
                    <i class="fa-regular fa-trash-can fa-lg"></i>
                </a>';
                $options .= '</div>';
                $row[]              = $options;
                $output['aaData'][] = $row;
            }
            echo json_encode($output);

            exit();
        }
        $data['title'] = _l('predefined_replies');
        $this->load->view('admin/tickets/predefined_replies/manage', $data);
    }

    public function get_predefined_reply_ajax($id)
    {
        echo json_encode($this->tickets_model->get_predefined_reply($id));
    }

    public function ticket_change_data()
    {
        if ($this->input->is_ajax_request()) {
            $contact_id = $this->input->post('contact_id');
            echo json_encode([
                'contact_data'          => $this->clients_model->get_contact($contact_id),
                'customer_has_projects' => customer_has_projects(get_user_id_by_contact_id($contact_id)),
            ]);
        }
    }

    // Add new reply or edit existing
    public function predefined_reply($id = '')
    {
        if (! is_admin() && get_option('staff_members_save_tickets_predefined_replies') == '0') {
            access_denied('Predefined Reply');
        }
        if ($this->input->post()) {
            $data              = $this->input->post();
            $data['message']   = html_purify($this->input->post('message', false));
            $ticketAreaRequest = isset($data['ticket_area']);

            if (isset($data['ticket_area'])) {
                unset($data['ticket_area']);
            }

            if ($id == '') {
                $id = $this->tickets_model->add_predefined_reply($data);
                if (! $ticketAreaRequest) {
                    if ($id) {
                        set_alert('success', _l('added_successfully', _l('predefined_reply')));
                        redirect(admin_url('tickets/predefined_reply/' . $id));
                    }
                } else {
                    echo json_encode(['success' => $id ? true : false, 'id' => $id]);

                    exit;
                }
            } else {
                $success = $this->tickets_model->update_predefined_reply($data, $id);
                if ($success) {
                    set_alert('success', _l('updated_successfully', _l('predefined_reply')));
                }
                redirect(admin_url('tickets/predefined_reply/' . $id));
            }
        }
        if ($id == '') {
            $title = _l('add_new', _l('predefined_reply'));
        } else {
            $predefined_reply         = $this->tickets_model->get_predefined_reply($id);
            $data['predefined_reply'] = $predefined_reply;
            $title                    = _l('edit', _l('predefined_reply')) . ' ' . $predefined_reply->name;
        }
        $data['title'] = $title;
        $this->load->view('admin/tickets/predefined_replies/reply', $data);
    }

    // Delete ticket reply from database
    public function delete_predefined_reply($id)
    {
        if (! is_admin()) {
            access_denied('Delete Predefined Reply');
        }
        if (! $id) {
            redirect(admin_url('tickets/predefined_replies'));
        }
        $response = $this->tickets_model->delete_predefined_reply($id);
        if ($response == true) {
            set_alert('success', _l('deleted', _l('predefined_reply')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('predefined_reply_lowercase')));
        }
        redirect(admin_url('tickets/predefined_replies'));
    }

    // Ticket statuses
    // Get all ticket statuses
    public function statuses()
    {
        if (! is_admin()) {
            access_denied('Ticket Statuses');
        }
        $data['statuses'] = $this->tickets_model->get_ticket_status();
        $data['title']    = 'Ticket statuses';
        $this->load->view('admin/tickets/tickets_statuses/manage', $data);
    }

    // Add new or edit existing status
    public function status()
    {
        if (! is_admin()) {
            access_denied('Ticket Statuses');
        }
        if ($this->input->post()) {
            if (! $this->input->post('id')) {
                $id = $this->tickets_model->add_ticket_status($this->input->post());
                if ($id) {
                    set_alert('success', _l('added_successfully', _l('ticket_status')));
                }
            } else {
                $data = $this->input->post();
                $id   = $data['id'];
                unset($data['id']);
                $success = $this->tickets_model->update_ticket_status($data, $id);
                if ($success) {
                    set_alert('success', _l('updated_successfully', _l('ticket_status')));
                }
            }

            exit;
        }
    }

    // Delete ticket status from database
    public function delete_ticket_status($id)
    {
        if (! is_admin()) {
            access_denied('Ticket Statuses');
        }
        if (! $id) {
            redirect(admin_url('tickets/statuses'));
        }
        $response = $this->tickets_model->delete_ticket_status($id);
        if (is_array($response) && isset($response['default'])) {
            set_alert('warning', _l('cant_delete_default', _l('ticket_status_lowercase')));
        } elseif (is_array($response) && isset($response['referenced'])) {
            set_alert('danger', _l('is_referenced', _l('ticket_status_lowercase')));
        } elseif ($response == true) {
            set_alert('success', _l('deleted', _l('ticket_status')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('ticket_status_lowercase')));
        }
        redirect(admin_url('tickets/statuses'));
    }

    // List all ticket services
    public function services()
    {
        if (! is_admin()) {
            access_denied('Ticket Services');
        }
        if ($this->input->is_ajax_request()) {
            $aColumns = [
                'serviceid',
                'name',
            ];
            $sIndexColumn = 'serviceid';
            $sTable       = db_prefix() . 'services';
            $result       = data_tables_init($aColumns, $sIndexColumn, $sTable, [], [], [
                'serviceid',
            ]);
            $output  = $result['output'];
            $rResult = $result['rResult'];

            foreach ($rResult as $aRow) {
                $row = [];

                for ($i = 0; $i < count($aColumns); $i++) {
                    $_data = $aRow[$aColumns[$i]];
                    if ($aColumns[$i] == 'name') {
                        $_data = '<a href="#" class="tw-font-medium" onclick="edit_service(this,' . $aRow['serviceid'] . ');return false" data-name="' . $aRow['name'] . '">' . $_data . '</a>';
                    }
                    $row[] = $_data;
                }

                $options = '<a href="#" onclick="edit_service(this,' . $aRow['serviceid'] . '); return false;"  data-name="' . $aRow['name'] . '"class="tw-text-neutral-500 hover:tw-text-neutral-700 focus:tw-text-neutral-700 tw-mr-2">
                <i class="fa-regular fa-pen-to-square fa-lg"></i>
            </a>';

                $options .= '<a href="' . admin_url('tickets/delete_service/' . $aRow['serviceid']) . '" class="tw-text-neutral-500 hover:tw-text-neutral-700 focus:tw-text-neutral-700 _delete">
            <i class="fa-regular fa-trash-can fa-lg"></i>
        </a>';

                $row[]              = $options;
                $output['aaData'][] = $row;
            }
            echo json_encode($output);

            exit();
        }
        $data['title'] = _l('services');
        $this->load->view('admin/tickets/services/manage', $data);
    }

    // Add new service od delete existing one
    public function service($id = '')
    {
        if (! is_admin() && get_option('staff_members_save_tickets_predefined_replies') == '0') {
            access_denied('Ticket Services');
        }

        if ($this->input->post()) {
            $post_data = $this->input->post();
            if (! $this->input->post('id')) {
                $requestFromTicketArea = isset($post_data['ticket_area']);
                if (isset($post_data['ticket_area'])) {
                    unset($post_data['ticket_area']);
                }
                $id = $this->tickets_model->add_service($post_data);
                if (! $requestFromTicketArea) {
                    if ($id) {
                        set_alert('success', _l('added_successfully', _l('service')));
                    }
                } else {
                    echo json_encode(['success' => $id ? true : false, 'id' => $id, 'name' => $post_data['name']]);
                }
            } else {
                $id = $post_data['id'];
                unset($post_data['id']);
                $success = $this->tickets_model->update_service($post_data, $id);
                if ($success) {
                    set_alert('success', _l('updated_successfully', _l('service')));
                }
            }

            exit;
        }
    }

    // Delete ticket service from database
    public function delete_service($id)
    {
        if (! is_admin()) {
            access_denied('Ticket Services');
        }
        if (! $id) {
            redirect(admin_url('tickets/services'));
        }
        $response = $this->tickets_model->delete_service($id);
        if (is_array($response) && isset($response['referenced'])) {
            set_alert('warning', _l('is_referenced', _l('service_lowercase')));
        } elseif ($response == true) {
            set_alert('success', _l('deleted', _l('service')));
        } else {
            set_alert('warning', _l('problem_deleting', _l('service_lowercase')));
        }
        redirect(admin_url('tickets/services'));
    }

    public function block_sender()
    {
        if ($this->input->post()) {
            $this->load->model('spam_filters_model');
            $sender  = $this->input->post('sender');
            $success = $this->spam_filters_model->add(['type' => 'sender', 'value' => $sender], 'tickets');
            if ($success) {
                set_alert('success', _l('sender_blocked_successfully'));
            }
        }
    }

    public function bulk_action()
    {
        hooks()->do_action('before_do_bulk_action_for_tickets');
        if ($this->input->post()) {
            $ids                  = $this->input->post('ids');
            $is_admin             = is_admin();
            $staffCanDeleteTicket = can_staff_delete_ticket();

            if (! is_array($ids)) {
                return;
            }

            if ($this->input->post('merge_tickets')) {
                $primary_ticket = $this->input->post('primary_ticket');
                $status         = $this->input->post('primary_ticket_status');

                if ($this->tickets_model->is_merged($primary_ticket)) {
                    set_alert('warning', _l('cannot_merge_into_merged_ticket'));

                    return;
                }

                $total_merged = $this->tickets_model->merge($primary_ticket, $status, $ids);
            } elseif ($this->input->post('mass_delete')) {
                $total_deleted = 0;
                if ($is_admin || $staffCanDeleteTicket) {
                    foreach ($ids as $id) {
                        if ($this->tickets_model->delete($id)) {
                            $total_deleted++;
                        }
                    }
                } else {
                    ajax_access_denied();

                    return;
                }
            } else {
                $status     = $this->input->post('status');
                $department = $this->input->post('department');
                $service    = $this->input->post('service');
                $priority   = $this->input->post('priority');
                $tags       = $this->input->post('tags');

                foreach ($ids as $id) {
                    if ($status) {
                        $this->db->where('ticketid', $id);
                        $this->db->update(db_prefix() . 'tickets', [
                            'status' => $status,
                        ]);
                    }
                    if ($department) {
                        $this->db->where('ticketid', $id);
                        $this->db->update(db_prefix() . 'tickets', [
                            'department' => $department,
                        ]);
                    }
                    if ($priority) {
                        $this->db->where('ticketid', $id);
                        $this->db->update(db_prefix() . 'tickets', [
                            'priority' => $priority,
                        ]);
                    }

                    if ($service) {
                        $this->db->where('ticketid', $id);
                        $this->db->update(db_prefix() . 'tickets', [
                            'service' => $service,
                        ]);
                    }
                    if ($tags) {
                        handle_tags_save($tags, $id, 'ticket');
                    }
                }
            }

            if ($this->input->post('mass_delete')) {
                set_alert('success', _l('total_tickets_deleted', $total_deleted));
            } elseif ($this->input->post('merge_tickets') && $total_merged > 0) {
                set_alert('success', _l('tickets_merged'));
            }
        }
    }

public function export_incident_reports_csv()
{
    if (!has_permission('tickets', '', 'view') && !is_admin()) {
        access_denied('tickets');
    }

    $this->load->model('tickets_model');

    // Build your own query or reuse your model method that returns rows
    $rows = $this->tickets_model->get_incident_report_export_rows(); // you created earlier

    $filename = 'incident_reports_' . date('Ymd_His') . '.csv';

    header('Content-Type: text/csv; charset=UTF-8');
    header('Content-Disposition: attachment; filename="'.$filename.'"');

    // Excel-friendly UTF-8 BOM
    echo "\xEF\xBB\xBF";

    $out = fopen('php://output', 'w');

    // Header row
    fputcsv($out, [
        'Ticket ID','Incident Subject','Date of Report',
        'Name','Email','Staff Position','Department','Incident Department',
        'HOD Status','HOD Date','HOD Comment',
        'Incident Type','Root Cause','Incident Category',
        'Priority','Responsible (Assignee)',
        'Incident Details','Incident Causes', 'Incident Resolved','Recommended Action Plans'
    ]);

    foreach ($rows as $r) {
        $department = $r['department_display'] ?: ($r['department_name'] ?? '');
        $assignee = trim(($r['assignee_name'] ?? ''));
        if (!empty($r['assignee_email'])) {
            $assignee .= ' <'.$r['assignee_email'].'>';
        }

        fputcsv($out, [
            $r['ticketid'] ?? '',
            $r['subject'] ?? '',
            $r['date'] ?? '',

            $r['staff_name'] ?? '',
            $r['staff_email'] ?? '',
            $r['staff_position'] ?? '',
            $department,
            $r['incident_department'] ?? '',

            $r['hod_status'] ?? '',
            $r['hod_date'] ?? '',
            $r['hod_comment'] ?? '',

            $r['incident_type'] ?? '',
            $r['root_cause'] ?? '',
            $r['incident_category_name'] ?? $r['incident_category_id'] ?? '',

            $r['priority_name'] ?? ($r['priority'] ?? ''),
            $assignee,

            $r['message'] ?? '',
            $r['incident_causes'] ?? '',
            $r['incident_resolved'] ?? '',
            $r['recommended_action_plans'] ?? '',
        ]);
    }

    fclose($out);
    exit;
}

    public function export_incident_report_excel__OLD($ticketId = null)
{
    if (!has_permission('tickets', '', 'view') && !has_permission('tickets', '', 'view_own') && !is_admin()) {
        access_denied('tickets');
    }

    $this->load->model('tickets_model');

    // If you want to export one ticket only:
    // $row = $this->tickets_model->get_incident_report_export_rows((int)$ticketId);
    // $rows = $row ? [$row] : [];

    // Export ALL incident reports:
    $rows = $this->tickets_model->get_incident_report_export_rows();

    // PhpSpreadsheet is commonly available in Perfex
    $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    $sheet->setTitle('Incident Reports');

    // Headers
    $headers = [
        'Ticket ID',
        'Incident Subject',
        'Date of Report',

        'Name',
        'Email address',
        'Staff Position',
        'Incident Department',

        'HOD Status',
        'HOD Date',
        'HOD Comment',

        'Incident Type',
        'Root Cause',
        'Incident Category',

        'Priority',
        'Responsible (Assignee)',

        'Incident Details',
        'Incident Causes',
        'Incident Resolved',
        'Recommended Action Plans',
    ];

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

    // Bold header row
    $sheet->getStyle('1:1')->getFont()->setBold(true);

    // Rows
    $r = 2;
    foreach ($rows as $row) {
        $department = $row['department_display'] ?: ($row['department_name'] ?? '');
        $assignee   = trim(($row['assignee_name'] ?? ''));
        if (!empty($row['assignee_email'])) {
            $assignee .= ' <' . $row['assignee_email'] . '>';
        }

        $sheet->setCellValueByColumnAndRow(1,  $r, $row['ticketid'] ?? '');
        $sheet->setCellValueByColumnAndRow(2,  $r, $row['subject'] ?? '');
        $sheet->setCellValueByColumnAndRow(3,  $r, $row['date'] ?? '');

        $sheet->setCellValueByColumnAndRow(4,  $r, $row['staff_name'] ?? '');
        $sheet->setCellValueByColumnAndRow(5,  $r, $row['staff_email'] ?? '');
        $sheet->setCellValueByColumnAndRow(6,  $r, $row['staff_position'] ?? '');
        $sheet->setCellValueByColumnAndRow(7,  $r, $row['incident_department'] ?? '');

        $sheet->setCellValueByColumnAndRow(8,  $r, ucfirst($row['hod_status'] ?? ''));
        $sheet->setCellValueByColumnAndRow(9,  $r, $row['hod_date'] ?? '');
        $sheet->setCellValueByColumnAndRow(10, $r, $row['hod_comment'] ?? '');

        $sheet->setCellValueByColumnAndRow(11, $r, $row['incident_type'] ?? '');
        $sheet->setCellValueByColumnAndRow(12, $r, $row['root_cause'] ?? '');
        $sheet->setCellValueByColumnAndRow(13, $r, $row['status'] ?? '');

        $sheet->setCellValueByColumnAndRow(14, $r, $row['priority_name'] ?? $row['priority'] ?? '');
        $sheet->setCellValueByColumnAndRow(15, $r, $assignee);

        $sheet->setCellValueByColumnAndRow(16, $r, $row['message'] ?? '');
        $sheet->setCellValueByColumnAndRow(17, $r, $row['incident_causes'] ?? '');
        $sheet->setCellValueByColumnAndRow(18, $r, $row['incident_resolved'] ?? '');
        $sheet->setCellValueByColumnAndRow(19, $r, $row['recommended_action_plans'] ?? '');

        $r++;
    }

    // Make long text readable
    $sheet->getStyle('P:R')->getAlignment()->setWrapText(true); // columns 16-18
    $sheet->getDefaultRowDimension()->setRowHeight(-1);

    // Auto-size columns A-R
    foreach (range('A', 'R') as $c) {
        $sheet->getColumnDimension($c)->setAutoSize(true);
    }

    // Output
    $filename = 'incident_reports_' . 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;
}




}
