<?php

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

/* * *****************Billing.php**********************************
 * @product name    : Hospital Management System
 * @type            : Class
 * @class name      : Billing
 * @description     : Manage billing.
 * @author          : South Bangla IT Zone Team
 * @url             : http://hms.sbitzone.com
 * @support         : rabibd.it@gmail.com
 * @copyright       : South Bangla IT Zone Team
 * ********************************************************** */

class Billing extends MY_Controller
{

    public $data = array();

    function __construct()
    {
        parent::__construct();
        $this->load->model('Billing_Model', 'billing', true);
        $this->data['marketings'] = $this->billing->get_marketing_list();
        $this->data['reference_employees'] = $this->billing->get_reference_employees_list();
        $this->data['reference_add'] = $this->billing->get_add_reference_list();
    }

    public function set_barcode($code)
    {
        // Load library
        $this->load->library('zend');
        // Load in folder Zend
        $this->zend->load('Zend/Barcode');
        // Generate barcode
        Zend_Barcode::render('code128', 'image', array('text' => $code, 'drawText' => false), array());
    }

    /*****************Function index**********************************
     * @type            : Function
     * @function name   : index
     * @description     : Load "Billing List" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */
    public function index()
    {

        check_permission(VIEW);

        $search = trim($this->input->get('search'));
        $config = array();
        $config = get_pagination(ADMIN_PER_PAGE);
        if ($search) {
            $config['base_url'] = site_url('billing/?search=' . $search);
        } else {
            $config['base_url'] = current_url();
        }
        if ($this->input->get('page')) {
            $sgm = (int) trim($this->input->get('page'));
            $offset = $config['per_page'] * ($sgm - 1);
        } else {
            $offset = 0;
        }

        $config['total_rows'] = $this->billing->get_patient_list($config['per_page'], $offset, $search, $count = TRUE);
        $this->pagination->initialize($config);
        $this->data['patients'] = $this->billing->get_patient_list($config['per_page'], $offset, $search, $count = FALSE);
        $this->data['sl_count'] = ($this->input->get('page') == 0 ? 1 : (($this->input->get('page') - 1) * $config["per_page"] + 1));
        $this->data['search'] = $search;


        $this->data['list'] = TRUE;
        $this->layout->title($this->lang->line('manage_billing') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/index', $this->data);
    }

    /*****************Function search**********************************
     * @type            : Function
     * @function name   : search
     * @description     : Load "Search Test Price" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function search()
    {
        $this->data['list'] = TRUE;
        $this->layout->title($this->lang->line('search') . ' ' . $this->lang->line('test_bill') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/search', $this->data);
    }

    /*****************Function addpatient**********************************
     * @type            : Function
     * @function name   : addpatient
     * @description     : Load "Add Patient" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */
    public function addpatient()
    {

        check_permission(ADD);

        if ($_POST) {
            $this->load->library('form_validation');
            $this->form_validation->set_error_delimiters('<div class="error-message" style="color: red;">', '</div>');
            $this->form_validation->set_rules('name', $this->lang->line('patient') . ' ' . $this->lang->line('name'), 'trim|required');
            $this->form_validation->set_rules('phone', $this->lang->line('phone'), 'trim|required|callback_phone');

            if ($this->form_validation->run() === TRUE) {
                $data['name'] = $this->input->post('name');
                $data['phone'] = $this->input->post('phone');
                $data['gender'] = $this->input->post('gender');
                $data['address'] = $this->input->post('address');
                $data['note'] = $this->input->post('note');

                // Age Calculation
                $age = abs((int) $this->input->post('age'));
                $month = abs((int) $this->input->post('month'));
                $day = abs((int) $this->input->post('day'));

                $str = date('Y-m-d');
                if ($age > 0) {
                    $str = $str . ' -' . $age . ' years';
                }
                if ($month > 0) {
                    $str = $str . ' -' . $month . ' months';
                }
                if ($day > 0) {
                    $str = $str . ' -' . ($day + 1) . ' days';
                }
                $dob = date("Y-m-d", strtotime($str));
                $data['dob'] = date('Y-m-d', strtotime($dob));
                $data['age'] = floor((time() - strtotime($data['dob'])) / 31556926);
                // End Age Calculation

                $data['discharged'] = 0;
                $data['status'] = 1;
                $data['created_at'] = date('Y-m-d H:i:s');
                $data['created_by'] = logged_in_user_id();
                // create patient_unique_id
                $data['patient_unique_id'] = $this->billing->get_custom_id('patients', '1');
                // create user
                $data['user_id'] = $this->billing->create_user();
                $insert_id = $this->billing->insert('patients', $data);
                if ($insert_id) {
                    create_log('Has been created a patient : ' . $data['name']);
                }
                $array = array('status' => 'success', 'message' => $this->lang->line('insert_success'), 'user_id' => $data['user_id']);
            } else {
                $this->data = $_POST;
                $msg = array(
                    'name' => form_error('name'),
                    'phone' => form_error('phone'),
                );
                $array = array('status' => 'failed', 'error' => $msg);
            }
            echo json_encode($array);
        }
    }

    /*****************Function addemployee**********************************
     * @type            : Function
     * @function name   : addemployee
     * @description     : Load "Add Employee" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */
    public function addemployee()
    {

        check_permission(ADD);

        if ($_POST) {
            $this->load->library('form_validation');
            $this->form_validation->set_error_delimiters('<div class="error-message" style="color: red;">', '</div>');
            $this->form_validation->set_rules('name', $this->lang->line('name') . ' ' . $this->lang->line('type'), 'trim|required|callback_commission_phone');
            $this->form_validation->set_rules('phone', $this->lang->line('phone'), 'trim|required');

            if ($this->form_validation->run() === TRUE) {
                $data['name'] = $this->input->post('name');
                $data['phone'] = $this->input->post('phone');
                $data['commission_type'] = $this->input->post('commission_type');

                $data['status'] = 1;
                $data['created_at'] = date('Y-m-d H:i:s');
                $data['created_by'] = logged_in_user_id();
                // create user
                $data['user_id'] = $this->billing->create_user();

                $insert_id = $this->billing->insert('employees', $data);
                if ($insert_id) {
                    create_log('Has been created a employee : ' . $data['name']);
                }
                $array = array('status' => 'success', 'message' => $this->lang->line('insert_success'), 'user_id' => $data['user_id']);
            } else {
                $this->data = $_POST;
                $msg = array(
                    'name' => form_error('name'),
                    'phone' => form_error('phone'),
                );
                $array = array('status' => 'failed', 'error' => $msg);
            }
            echo json_encode($array);
        }
    }

    /*****************Function commission_phone**********************************
     * @type            : Function
     * @function name   : commission_phone
     * @description     : Unique check for "Commission Phone" data/value
     *
     * @param           : null
     * @return          : boolean true/false
     * ********************************************************** */
    public function commission_phone()
    {
        if ($this->input->post('id') == '') {
            $commission = $this->billing->duplicate_check_commission_phone($this->input->post('phone'));
            if ($commission) {
                $this->form_validation->set_message('commission_phone', $this->lang->line('phone_already_exist'));
                return FALSE;
            } else {
                return TRUE;
            }
        } else if ($this->input->post('id') != '') {
            $commission = $this->billing->duplicate_check_commission_phone($this->input->post('phone'), $this->input->post('id'));
            if ($commission) {
                $this->form_validation->set_message('commission_phone',  $this->lang->line('phone_already_exist'));
                return FALSE;
            } else {
                return TRUE;
            }
        } else {
            return TRUE;
        }
    }

    /*****************Function phone**********************************
     * @type            : Function
     * @function name   : phone
     * @description     : Unique check for "Patient Phone" data/value
     *
     * @param           : null
     * @return          : boolean true/false
     * ********************************************************** */
    public function phone()
    {
        if ($this->input->post('id') == '') {
            $patient = $this->billing->duplicate_check($this->input->post('name'), $this->input->post('phone'));
            if ($patient) {
                $this->form_validation->set_message('phone', $this->lang->line('phone_already_exist'));
                return FALSE;
            } else {
                return TRUE;
            }
        } else if ($this->input->post('id') != '') {
            $patient = $this->billing->duplicate_check($this->input->post('name'), $this->input->post('phone'), $this->input->post('id'));
            if ($patient) {
                $this->form_validation->set_message('phone',  $this->lang->line('phone_already_exist'));
                return FALSE;
            } else {
                return TRUE;
            }
        } else {
            return TRUE;
        }
    }

    /*****************Function index**********************************
     * @type            : Function
     * @function name   : index
     * @description     : Load "Billing List" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function create($user_id = null)
    {

        check_permission(ADD);
        $this->data['created'] = $this->billing->get_single('invoices', array('id' => $this->input->get('invoice')));
        $this->data['patient'] = $this->billing->get_single('patients', array('user_id' => $this->uri->segment(3, 0)));
        $this->data['doctor'] = $this->billing->get_patient_by_ref_dr($this->uri->segment(3, 0));
        $appointment = $this->billing->get_single_appointment($this->uri->segment(3, 0));
        $date = @$appointment->created_at ? date('Y-m-d', strtotime($appointment->created_at)) : null;
        $reference = $this->billing->get_single_reference($this->uri->segment(3, 0));
        $reference_day_count = get_days_between(@$reference->appointment_date, date('Y-m-d')) + 1;
        $this->data['reference'] = $this->billing->get_patient_by_reference($this->uri->segment(3, 0), $reference->commission_type ?? null, $date);
        $this->data['is_reference'] = $reference_day_count <= $this->global_setting->reference_days;
        $this->data['employees'] = $this->billing->get_employee_list();
        $this->data['authorized_person'] = $this->billing->get_authorized_person_list();
        $this->data['tubes'] = $this->billing->get_list('diagnostic_tubes', array('status' => 1), '', '', '', 'sort_by', 'ASC');

        $this->data['marketing'] = $this->billing->get_marketing_opd_patient($user_id);

        $this->data['add'] = TRUE;
        $this->layout->title($this->lang->line('create') . ' ' . $this->lang->line('billing') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/create', $this->data);
    }

    /*****************Function add**********************************
     * @type            : Function
     * @function name   : add
     * @description     : Load "add Billing" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function add()
    {

        check_permission(ADD);

        if ($_POST) {
            if (!$this->input->post('authorized_person')) {
                $total_bill = 0;
                $total_special_discount = 0;
                foreach ($this->input->post('tests') as $tid => $qty) {
                    $test_details = (array) $this->billing->get_single('diagnostic_tests', array('id' => $tid));
                    if ($test_details) {
                        $total_bill += ($test_details['rate'] * $qty);
                        $total_special_discount += ($test_details['special_discount'] * $qty);
                    }
                }

                $tube_sum_d = 0;
                if ($this->input->post('tubes')) {
                    foreach ($this->input->post('tubes') as $tube_id => $qty) {
                        $tube = $this->billing->get_single('diagnostic_tubes', array('id' => $tube_id));
                        $tube_sum_d += ($tube->price * $qty);
                    }
                }

                $is_discount = ($this->global_setting->is_discount / 100) * (($total_bill + $tube_sum_d) - $total_special_discount);
                $discount = $this->input->post('commission') != 'null' && $this->input->post('commission') > 0;
                if ($discount > $is_discount) {
                    $array = array('status' => 'failed', 'error' => "Warning! Attention Please!!! <br> Discount amount is not more than " . $is_discount);
                    echo json_encode($array);
                    exit();
                }
            }

            if (!$this->input->post('self') && !$this->input->post('doctor_id')) {
                $array = array('status' => 'failed', 'error' => "Doctor or Self must be select");
                echo json_encode($array);
                exit();
            }
            if (count($this->input->post('tests')) == 0) {
                $this->data = $_POST;
                $array = array('status' => 'failed', 'error' => "No test selected");
                echo json_encode($array);
                exit();
            }

            $data['custom_invoice_id'] = get_custom_id('invoices', 'INV-', date('Y'), date('m'));
            $data['invoice_type'] = 'investigation';
            $data['patient_id'] = $this->input->post('patient_id');

            // Ref By Doctor Query
            $doctor_id = explode('-', $this->input->post('doctor_id'));
            $ref_dr_id = $this->billing->get_single('employees', array('user_id' =>  $doctor_id[0]));
            if ($this->input->post('self') == 1) {
                $data['self'] = '1';
                $data['ref_dr_id'] = NULL;
                $data['ref_dr_name'] = NULL;
            } else {
                if (isset($ref_dr_id->user_id)) {
                    $data['ref_dr_id'] = $doctor_id[0];
                } else {
                    $data['ref_dr_name'] = $this->input->post('doctor_id');
                }
            }
            $commission_user_id = explode('-', $this->input->post('commission_user_id'));
            $coms = $this->billing->get_single('employees', array('id' =>  $commission_user_id[0]));

            if (isset($coms->user_id)) {
                $data['commission_user_id'] = $coms->user_id;
                $data['commission_under_marketing'] = $coms->marketing_id && $coms->commission_type == 'vd' ? $coms->marketing_id : null;
            } else {
                $data['commission_name'] = $this->input->post('commission_user_id');
            }

            // reference employee
            $reference_emp = explode('-', $this->input->post('reference_employee'));
            $emps = $this->billing->get_single('employees', array('id' =>  $reference_emp[0]));

            if (isset($emps->user_id)) {
                $data['reference_employee'] = $emps->user_id;
            } else {
                $data['reference_employee'] = null;
            }

            $data['bill_date'] = $this->session->userdata('role_id') == ADMIN ? date('Y-m-d H:i:s', strtotime($this->input->post('bill_date'))) : date('Y-m-d H:i:s');
            $data['delivery_status'] = $this->input->post('urgent') == 1 ? 'urgent' : 'normal';

            $tube_sum = 0;
            if ($this->input->post('tubes')) {
                foreach ($this->input->post('tubes') as $tube_id => $qty) {
                    $tube = $this->billing->get_single('diagnostic_tubes', array('id' => $tube_id));
                    $tube_sum += ($tube->price * $qty);
                }
            }

            // Under Construction
            $data['total_bill'] = $tube_sum; //
            $data['commission_amount'] = '0.00'; //
            $data['special_discount'] = '0.00'; //
            $data['prev_invoice_id'] = $this->input->post('prev_invoice_id') ?? null; //


            $data['discount'] = $this->input->post('discount') != 'null' && $this->input->post('discount') > 0 ? $this->input->post('discount') : '0.00';
            $data['advanced'] = $this->input->post('advanced') != 'null' && $this->input->post('advanced') > 0 ? $this->input->post('advanced') : '0.00';
            $data['payable_commission'] = $this->input->post('commission') != 'null' && $this->input->post('commission') > 0 ? $this->input->post('commission') : '0.00';
            foreach ($this->input->post('tests') as $tid => $qty) {
                $test_details = (array) $this->billing->get_single('diagnostic_tests', array('id' => $tid));
                if ($test_details) {
                    $data['total_bill'] += ($test_details['rate'] * $qty);
                    if ($coms) {
                        $data['commission_amount'] += ($test_details[$coms->commission_type] * $qty);
                    }
                }
            }
            if ($coms) {
                $data['commission_amount'] = $data['total_bill'] - ($data['commission_amount'] + $tube_sum);
            } else {
                $data['commission_amount'] = 0;
            }
            $data['net_payable'] = $data['total_bill'];
            $data['paid_status'] = 'unpaid'; //
            if ($data['discount'] > 0) {
                $data['net_payable'] -=  $data['discount'];
            }
            $data['due_amount'] = $data['net_payable'];
            if ($data['advanced'] > 0) {
                $data['due_amount'] -=  $data['advanced'];
            }
            if ($data['due_amount'] <= 0) {
                $data['paid_status'] = 'paid'; //
            }


            $data['date'] = $this->session->userdata('role_id') == ADMIN ? date('Y-m-d', strtotime($this->input->post('bill_date'))) : date('Y-m-d');
            $data['month'] = $this->session->userdata('role_id') == ADMIN ? date('m', strtotime($this->input->post('bill_date'))) : date('m');
            $data['year'] = $this->session->userdata('role_id') == ADMIN ? date('Y', strtotime($this->input->post('bill_date'))) : date('Y');
            $data['note'] = $this->input->post('note') ? $this->input->post('note') : null;

            $data['status'] = 1;
            $data['authorized_person'] = $this->input->post('authorized_person') ? $this->input->post('authorized_person') : null;

            $appointment = $this->billing->get_single_appointment($data['patient_id']);
            $marketing = $this->billing->get_single('invoices', ['appointment_id' => @$appointment->id, 'marketing_id' => @$appointment->created_by], '', '', '', 'id', 'ASC');
            $data['appointment_id'] = isset($appointment->id) && $appointment->id > 0 ? $appointment->id : null;
            if (isset($marketing->marketing_id) && !empty($marketing->marketing_id)) {
                $data['marketing_id'] = null;
            } else {
                $data['marketing_id'] = $appointment->created_by ?? null;
            }

            // print_r($data);
            //die();
            //$data['appointment_id'] = $this->input->post('appointment_id') ? $this->input->post('appointment_id') : null;
            //$data['marketing_id'] = $this->input->post('marketing_id') ? $this->input->post('marketing_id') : null;

            $data['created_at'] = date('Y-m-d H:i:s');
            if ($this->input->post('created_by') > 0 && !empty($this->input->post('created_by'))) {
                $data['created_by'] = $this->input->post('created_by');
            } else {
                $data['created_by'] = logged_in_user_id();
            }

            $this->db->trans_start();
            $insert_id = $this->billing->insert('invoices', $data);
            // Insert Test for Invoice Details
            $tests = $this->input->post('tests');

            if (isset($tests) && !empty($tests)) {
                foreach ($this->input->post('tests') as $tid => $qty) {
                    $test_details = $this->billing->get_single('diagnostic_tests', array('id' => $tid));
                    $testdata['invoice_id'] = $insert_id;
                    $testdata['investagation_id'] = $test_details->id;
                    $testdata['unit'] = $qty; //
                    $testdata['rate'] = $test_details->rate;
                    $testdata['total_rate'] = ($testdata['unit'] * $testdata['rate']);

                    $testdata['discount'] = $test_details->special_discount;
                    $testdata['total_discount'] = ($testdata['unit'] * $test_details->special_discount);

                    $testdata['status'] = 1;
                    $testdata['created_at'] = date('Y-m-d H:i:s');
                    if ($this->input->post('created_by') > 0 && !empty($this->input->post('created_by'))) {
                        $testdata['created_by'] = $this->input->post('created_by');
                    } else {
                        $testdata['created_by'] = logged_in_user_id();
                    }

                    if ($testdata['total_discount'] > 0) {
                        $data['special_discount'] += $testdata['total_discount'];
                    }

                    $this->billing->insert('invoice_details', $testdata);
                }

                if ($data['special_discount'] > 0) {
                    $data['paid_status'] = 'unpaid';
                    $data['net_payable'] -= $data['special_discount'];
                    $data['due_amount'] -= $data['special_discount'];
                    if ($data['due_amount'] <= 0) {
                        $data['paid_status'] = 'paid'; //
                        $data['due_amount'] = 0; //
                    }
                    $this->billing->update('invoices', array(
                        'special_discount' => $data['special_discount'],
                        'due_amount' => $data['due_amount'],
                        'net_payable' => $data['net_payable'],
                        'paid_status' => $data['paid_status']
                    ), array('id' => $insert_id));
                }
            }


            // Tube Details

            $tubes = $this->input->post('tubes');
            if (isset($tubes) && !empty($tubes)) {
                foreach ($this->input->post('tubes') as $tube_id => $qty) {
                    $tube_details = $this->billing->get_single('diagnostic_tubes', array('id' => $tube_id));
                    $tubedata['invoice_id'] = $insert_id;
                    $tubedata['tube_id'] = $tube_id;
                    $tubedata['quantity'] = $qty;
                    $tubedata['rate'] = $tube_details->price;
                    $tubedata['total_rate'] = ($tubedata['quantity'] * $tubedata['rate']);
                    $tubedata['status'] = 1;
                    $tubedata['created_at'] = date('Y-m-d H:i:s');
                    if ($this->input->post('created_by') > 0 && !empty($this->input->post('created_by'))) {
                        $tubedata['created_by'] = $this->input->post('created_by');
                    } else {
                        $tubedata['created_by'] = logged_in_user_id();
                    }
                    $this->billing->insert('invoice_tube_details', $tubedata);
                }
            }


            // Payment Invoice Data

            $paymentdata['invoice_id'] = $insert_id;
            $paymentdata['collection_type'] = '1';
            $paymentdata['payment_date'] = $this->session->userdata('role_id') == ADMIN ? date('Y-m-d', strtotime($this->input->post('bill_date'))) : date('Y-m-d');
            $data['date'] = $this->session->userdata('role_id') == ADMIN ? date('Y-m-d', strtotime($this->input->post('bill_date'))) : date('Y-m-d');
            $data['month'] = $this->session->userdata('role_id') == ADMIN ? date('m', strtotime($this->input->post('bill_date'))) : date('m');
            $data['year'] = $this->session->userdata('role_id') == ADMIN ? date('Y', strtotime($this->input->post('bill_date'))) : date('Y');
            $paymentdata['amount'] = $this->input->post('advanced') ? $this->input->post('advanced') : '0.00';
            $paymentdata['status'] = 1;
            $paymentdata['created_at'] = date('Y-m-d H:i:s');
            if ($this->input->post('created_by') > 0 && !empty($this->input->post('created_by'))) {
                $paymentdata['created_by'] = $this->input->post('created_by');
            } else {
                $paymentdata['created_by'] = logged_in_user_id();
            }

            $this->billing->insert('invoice_payments', $paymentdata);

            if (has_permission(ADD, 'billing', 'billing_sms')) {
                send_sms('billing_sms', $insert_id);
            }

            $this->db->trans_complete();
            if ($this->db->trans_status() === FALSE) {
                $array = array('status' => 'failled', 'message' => $this->lang->line('insert_success'));
                echo json_encode($array);
                die;
            }

            if ($insert_id) {
                create_log('Has been created a invoice : ' . $data['custom_invoice_id']);
            }
            $array = array('status' => 'success', 'message' => $this->lang->line('insert_success'), 'id' => $insert_id);

            echo json_encode($array);
        }
    }

    /*****************Function bill**********************************
     * @type            : Function
     * @function name   : bill
     * @description     : Load "Billing List" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function bill()
    {

        check_permission(VIEW);

        if ($_GET && $this->input->get('date')) {
            $type = $this->input->get('type');
            $date = $this->input->get('date');
            $exp = explode('-', $date);
            $form_date = date('Y-m-d', strtotime($exp[0]));
            $to_date = date('Y-m-d', strtotime($exp[1]));
            $search = trim($this->input->get('search'));
            $config = array();
            $config = get_pagination(ADMIN_PER_PAGE);
            $config['base_url'] = site_url('billing/bill/?type=' . $type . '&date=' . $date . '&search=' . $search);
            if ($this->input->get('page')) {
                $sgm = (int) trim($this->input->get('page'));
                $offset = $config['per_page'] * ($sgm - 1);
            } else {
                $offset = 0;
            }

            $config['total_rows'] = $this->billing->get_bill_list($config['per_page'], $offset, $type, $form_date, $to_date, $search, $count = TRUE);
            $this->pagination->initialize($config);
            $this->data['bills'] = $this->billing->get_bill_list($config['per_page'], $offset, $type, $form_date, $to_date, $search, $count = FALSE);
            $this->data['sl_count'] = ($this->input->get('page') == 0 ? 1 : (($this->input->get('page') - 1) * $config["per_page"] + 1));
            $this->data['search'] = $search;
            $this->data['date'] = $date;
            $this->data['type'] = $type;
        } else {
            $config = array();
            $config = get_pagination(ADMIN_PER_PAGE);
            $config['base_url'] = current_url();
            if ($this->input->get('page')) {
                $sgm = (int) trim($this->input->get('page'));
                $offset = $config['per_page'] * ($sgm - 1);
            } else {
                $offset = 0;
            }

            $config['total_rows'] = $this->billing->get_bill_list($config['per_page'], $offset, null, date('Y-m-d'), date('Y-m-d'), null, $count = TRUE);
            $this->pagination->initialize($config);
            $this->data['bills'] = $this->billing->get_bill_list($config['per_page'], $offset, null, date('Y-m-d'), date('Y-m-d'), null, $count = FALSE);
            $this->data['sl_count'] = ($this->input->get('page') == 0 ? 1 : (($this->input->get('page') - 1) * $config["per_page"] + 1));
        }
        $this->data['bill'] = TRUE;
        $this->layout->title($this->lang->line('bill') . ' ' . $this->lang->line('list') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/bill', $this->data);
    }

    /*****************Function getInvoiceId**********************************
     * @type            : Function
     * @function name   : getInvoiceId
     * @description     : Load "getInvoiceId" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function getInvoiceId($id)
    {
        $invoice = $this->billing->get_single('invoices', array('id' =>  $id));
        echo json_encode($invoice);
    }
    /*****************Function payment_status**********************************
     * @type            : Function
     * @function name   : payment_status
     * @description     : Load "payment_status" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function payment_status()
    {

        check_permission(EDIT);

        if ($_POST) {
            $this->load->library('form_validation');
            $this->form_validation->set_error_delimiters('<div class="error-message" style="color: red;">', '</div>');
            $this->form_validation->set_rules('payment_status', $this->lang->line('payment') . ' ' . $this->lang->line('status'), 'trim|required');

            if ($this->form_validation->run() === TRUE) {
                $data['payment_status'] = $this->input->post('payment_status');
                $data['note'] = $this->input->post('note');

                $data['modified_at'] = date('Y-m-d H:i:s');
                $data['modified_by'] = logged_in_user_id();

                $updated_id = $this->billing->update('invoices', $data, array('id' => $this->input->post('invoice_id')));
                if ($updated_id) {
                    create_log('Has been update a invoice : ' . $this->input->post('invoice_id'));
                }
                $array = array('status' => 'success', 'message' => $this->lang->line('update_success'));
            } else {
                $this->data = $_POST;
                $msg = array(
                    'payment_status' => form_error('payment_status')
                );
                $array = array('status' => 'failed', 'error' => $msg);
            }
            echo json_encode($array);
        }
    }

    /*****************Function due**********************************
     * @type            : Function
     * @function name   : due
     * @description     : Load "Due Billing List" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function due()
    {

        check_permission(VIEW);

        if ($_GET) {
            $search = $this->input->get('search');
            $exp = explode('-', $search);
            $formDate = date('Y-m-d', strtotime($exp[0]));
            $toDate = date('Y-m-d', strtotime($exp[1]));

            $config = array();
            $config = get_pagination(ADMIN_PER_PAGE);
            if ($search) {
                $config['base_url'] = site_url('billing/due/?search=') . $search;
            } else {
                $config['base_url'] = current_url();
            }
            if ($this->input->get('page')) {
                $sgm = (int) trim($this->input->get('page'));
                $offset = $config['per_page'] * ($sgm - 1);
            } else {
                $offset = 0;
            }

            $config['total_rows'] = $this->billing->get_due_bill_list($config['per_page'], $offset, $formDate, $toDate, $count = TRUE);
            $this->pagination->initialize($config);
            $this->data['dues'] = $this->billing->get_due_bill_list($config['per_page'], $offset, $formDate, $toDate, $count = FALSE);

            $this->data['sl_count'] = ($this->input->get('page') == 0 ? 1 : (($this->input->get('page') - 1) * $config["per_page"] + 1));
            $this->data['form_date'] = $formDate;
            $this->data['to_date'] = $toDate;
            $this->data['search'] = $search;
        }
        $this->layout->title($this->lang->line('due') . ' ' . $this->lang->line('billing') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/due', $this->data);
    }

    /*****************Function paid**********************************
     * @type            : Function
     * @function name   : paid
     * @description     : Load "Paid Billing List" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function paid()
    {

        check_permission(VIEW);

        if ($_GET) {
            $search = $this->input->get('search');
            $exp = explode('-', $search);
            $formDate = date('Y-m-d', strtotime($exp[0]));
            $toDate = date('Y-m-d', strtotime($exp[1]));

            $config = array();
            $config = get_pagination(ADMIN_PER_PAGE);
            if ($search) {
                $config['base_url'] = site_url('billing/paid/?search=') . $search;
            } else {
                $config['base_url'] = current_url();
            }
            if ($this->input->get('page')) {
                $sgm = (int) trim($this->input->get('page'));
                $offset = $config['per_page'] * ($sgm - 1);
            } else {
                $offset = 0;
            }

            $config['total_rows'] = $this->billing->get_paid_bill_list($config['per_page'], $offset, $formDate, $toDate, $count = TRUE);
            $this->pagination->initialize($config);
            $this->data['paids'] = $this->billing->get_paid_bill_list($config['per_page'], $offset, $formDate, $toDate, $count = FALSE);

            $this->data['sl_count'] = ($this->input->get('page') == 0 ? 1 : (($this->input->get('page') - 1) * $config["per_page"] + 1));
            $this->data['search'] = $search;
        }
        $this->layout->title($this->lang->line('paid') . ' ' . $this->lang->line('billing') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/paid', $this->data);
    }

    /*****************Function invoice**********************************
     * @type            : Function
     * @function name   : invoice
     * @description     : Load "InvoiceList" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function invoice()
    {

        check_permission(VIEW);

        $this->data['patient'] = $this->billing->get_patient_invoice($this->uri->segment(3, 0));
        $this->data['tests'] = $this->billing->get_patient_invoice_test($this->uri->segment(3, 0));
        $this->data['tubes'] = $this->billing->get_invoice_tube_list($this->uri->segment(3, 0));
        $this->data['invoice'] = $this->billing->get_single('invoices', array('id' => $this->uri->segment(3, 0)));
        $this->layout->title($this->lang->line('invoice') . ' ' . $this->lang->line('list') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/invoice', $this->data);
    }

    /*****************Function print**********************************
     * @type            : Function
     * @function name   : print
     * @description     : Load "print" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function print()
    {
        $this->load->library('Numbertowords');
        $this->data['patient'] = $this->billing->get_patient_invoice($this->input->post('id'));
        $this->data['tests'] = $this->billing->get_patient_invoice_test($this->input->post('id'));
        $this->data['tubes'] = $this->billing->get_invoice_tube_list($this->input->post('id'));
        $this->data['total_department'] = $this->billing->get_total_department($this->input->post('id'));
        $this->data['total_department_three'] = $this->billing->get_total_three_department($this->input->post('id'));
        $this->data['invoice'] = $this->billing->get_single('invoices', array('id' => $this->input->post('id')));
        $this->data['rooms'] = $this->billing->get_room_list($this->input->post('id'));
        $this->load->view('billing/print', $this->data);
    }

    /*****************Function print**********************************
     * @type            : Function
     * @function name   : print
     * @description     : Load "print" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function print_office()
    {
        $this->load->library('Numbertowords');
        $this->data['patient'] = $this->billing->get_patient_invoice($this->input->post('id'));
        $this->data['tests'] = $this->billing->get_patient_invoice_test($this->input->post('id'));
        $this->data['tubes'] = $this->billing->get_invoice_tube_list($this->input->post('id'));
        $this->data['total_department'] = $this->billing->get_total_department($this->input->post('id'));
        $this->data['invoice'] = $this->billing->get_single('invoices', array('id' => $this->input->post('id')));
        $this->data['rooms'] = $this->billing->get_room_list($this->input->post('id'));
        $this->load->view('billing/print-1', $this->data);
    }

    /*****************Function history**********************************
     * @type            : Function
     * @function name   : history
     * @description     : Load "Invoice history user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function history()
    {
        $this->data['collection_employees'] = $this->billing->get_employee_list();
        $this->data['patient'] = $this->billing->get_patient_invoice($this->uri->segment(3, 0));
        $this->data['invoice'] = $this->billing->get_single('invoices', array('id' => $this->uri->segment(3, 0)));
        $this->data['invoice_payments'] = $this->billing->get_patient_payment_history($this->uri->segment(3, 0));

        $this->layout->title($this->lang->line('invoice') . ' ' . $this->lang->line('history') . ' | ' . $this->global_setting->brand_title);
        $this->layout->view('billing/history', $this->data);
    }

    /*****************Function print_history**********************************
     * @type            : Function
     * @function name   : print_history
     * @description     : Load "print_history" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function print_history()
    {
        $this->data['patient'] = $this->billing->get_patient_invoice($this->input->post('id'));
        $this->data['invoice'] = $this->billing->get_single('invoices', array('id' => $this->input->post('id')));
        $this->data['invoice_payments'] = $this->billing->get_patient_payment_history($this->input->post('id'));
        $this->load->view('billing/print_history', $this->data);
    }

    public function add_payment()
    {

        check_permission(ADD);

        if ($_POST) {
            $data['invoice_id'] = $this->input->post('invoice_id');
            $data['collection_type'] = '2';
            // $data['payment_date'] = $this->input->post('date') ? date('Y-m-d H:i:s', strtotime($this->input->post('date'))) : NULL;
            $data['payment_date'] = $this->session->userdata('role_id') == ADMIN ? date('Y-m-d H:i:s', strtotime($this->input->post('date'))) : date('Y-m-d H:i:s');
            $data['amount'] = $this->input->post('amount') ?? 0;
            $data['second_less'] = !empty($this->input->post('second_less')) && $this->input->post('second_less') ? $this->input->post('second_less') : 0;
            $data['note'] = $this->input->post('note');


            if ($this->input->post('user') && $this->input->post('user') == 1) {

                $user = $this->billing->get_single('invoices', array('id' => $data['invoice_id']));
                if ($user->due_amount >= $data['amount']) {
                    $user_data['due_amount'] =   ($user->due_amount - ($data['amount'] + $data['second_less']));
                    $user_data['advanced'] =   ($user->advanced + $data['amount']);
                    $user_data['discount'] =   ($user->discount + $data['second_less']);
                    $user_data['paid_status'] =  $user_data['due_amount'] <= 0 ? 'paid' : 'unpaid';

                    $this->billing->update('invoices', $user_data, array('id' =>  $user->id));
                } else {
                    $array = array('status' => 'failed', 'error' => 'Please payment amount is less than or equal to the due amount.', 'message' => '');
                }
            } else {

                $admin = $this->billing->get_single('invoices', array('id' => $data['invoice_id']));
                if ($admin->due_amount >= $data['amount']) {

                    if ($data['second_less'] > 0) {
                        $admin_data['net_payable'] =   $admin->net_payable - $data['second_less'];
                    }
                    $admin_data['due_amount'] =   ($admin->due_amount - ($data['amount'] + $data['second_less']));
                    $admin_data['advanced'] =   ($admin->advanced + $data['amount']);
                    $admin_data['discount'] =   ($admin->discount + $data['second_less']);
                    $admin_data['paid_status'] =  $admin_data['due_amount'] <= 0 ? 'paid' : 'unpaid';

                    $this->billing->update('invoices', $admin_data, array('id' =>  $admin->id));
                } else {
                    $array = array('status' => 'failed', 'error' => 'Please payment amount is less than or equal to the due amount.', 'message' => '');
                }
            }

            $data['status'] = 1;
            $data['created_at'] = date('Y-m-d H:i:s');
            $data['created_by'] = logged_in_user_id();

            $insert_id = $this->billing->insert('invoice_payments', $data);

            if (has_permission(ADD, 'billing', 'billing_payment_sms')) {
                send_sms('billing_payment_sms', $insert_id);
            }

            create_log('Has been created a payment : ' . $data['invoice_id']);
            $array = array('status' => 'success', 'error' => '', 'message' => $this->lang->line('insert_success'));
        } else {
            $msg = array(
                'amount' => form_error('amount'),
            );
            $array = array('status' => 'failed', 'error' => $msg, 'message' => '');
        }

        echo json_encode($array);
    }

    /*****************Function get_payment_data**********************************
     * @type            : Function
     * @function name   : get_payment_data
     * @description     : Load "Payment Amount" user interface
     *
     * @param           : null
     * @return          : null
     * ********************************************************** */

    public function get_payment_data()
    {
        $invoice = $this->billing->get_single('invoices', array('id' => $this->uri->segment(3, 0)));
        $amount = array('amount' => $invoice->due_amount);
        echo json_encode($amount);
    }

    public function test_search()
    {
        $search = $this->billing->get_test_search($this->input->post('name'));
        echo json_encode($search);
    }

    public function doctor_search()
    {
        $search = $this->billing->get_doctor_search($this->input->post('name'));
        echo json_encode($search);
    }

    public function commission_search()
    {
        $search = $this->billing->get_commission_search($this->input->post('name'));
        echo json_encode($search);
    }

    public function employee_search()
    {
        $search = $this->billing->get_employee_search($this->input->post('name'));
        echo json_encode($search);
    }

    public function get_invoice($invoice_id)
    {
        $search = $this->billing->get_single('invoices', array('id' => $invoice_id));
        $doctor_name = $search->ref_dr_name;
        $doctor = null;
        if ($search->ref_dr_id) {
            $doctor = $this->billing->get_single('employees', array('user_id' => $search->ref_dr_id));
        }

        $com_name = $search->commission_name;
        $commission = null;
        if ($search->commission_user_id) {
            $commission = $this->billing->get_single('employees', array('user_id' => $search->commission_user_id));
        }
        $test = $this->billing->get_list('invoice_details', array('invoice_id' => $invoice_id));
        $investagations = [];
        foreach ($test as $item) {
            $singe_test = $this->billing->get_single('diagnostic_tests', array('id' => $item->investagation_id));
            $singe_test->quantity = $item->unit;
            array_push($investagations, $singe_test);
        }
        $tube = $this->billing->get_list('invoice_tube_details', array('invoice_id' => $invoice_id));
        $tubes = [];
        foreach ($tube as $item) {
            $singe_tube = $this->billing->get_single('diagnostic_tubes', array('id' => $item->tube_id));
            $singe_tube->quantity = $item->quantity;
            $singe_tube->rate = $item->rate;
            array_push($tubes, $singe_tube);
        }
        echo json_encode([
            'invoice' => $search,
            'tests' => $investagations,
            'tubes' => $tubes,
            'doctor_name' => $doctor_name,
            'doctor' => $doctor,
            'com_name' => $com_name,
            'commission' => $commission
        ]);
    }

    /*     * ***************Function delete**********************************
     * @type            : Function
     * @function name   : delete
     * @description     : delete "Invoice Delete" data from database
     *                     and unlink all information server
     * @param           : $id integer value
     * @return          : null
     * ********************************************************** */

    public function delete($id = null)
    {

        check_permission(DELETE);

        if (!is_numeric($id)) {
            error($this->lang->line('unexpected_error'));
            redirect('billing/bill');
        }

        $invoice = $this->billing->get_single('invoices', array('id' => $id));
        if (!empty($invoice)) {

            // delete invoice data
            $this->billing->delete('invoices', array('id' => $id));
            // delete invoice details data
            $this->billing->delete('invoice_details', array('invoice_id' => $invoice->id));

            // delete invoice payment data
            $this->billing->delete('invoice_payments', array('invoice_id' => $invoice->id));

            create_log('Has been deleted a invoice : ' . $invoice->id . '-> [' . $invoice->custom_invoice_id . ']');
            success($this->lang->line('delete_success'));
        } else {
            error($this->lang->line('delete_failed'));
        }
        redirect('billing/bill');
    }

    public function billing_sms($id = null)
    {
        check_permission(VIEW);
        if ($id) {
            send_sms('billing_sms', $id);
        }
    }

    public function payment_collection()
    {
        if ($_POST) {

            $data['invoice_id'] = $this->input->post('invoice_id');
            $data['collection_type'] = '2';
            // $data['payment_date'] = $this->input->post('date') ? date('Y-m-d H:i:s', strtotime($this->input->post('date'))) : date('Y-m-d H:i:s');
            $data['payment_date'] = $this->session->userdata('role_id') == ADMIN ? date('Y-m-d H:i:s', strtotime($this->input->post('date'))) : date('Y-m-d H:i:s');
            $data['amount'] = $this->input->post('amount') ?? 0;
            $data['second_less'] = !empty($this->input->post('discount')) && $this->input->post('discount') ? $this->input->post('discount') : 0;
            $data['note'] = $this->input->post('note');

            $admin = $this->billing->get_single('invoices', array('id' => $data['invoice_id']));
            $netPay = $admin->net_payable - $admin->advanced;
            if ($netPay >= $data['amount']) {
                if ($data['second_less'] > 0) {
                    $admin_data['net_payable'] =   $admin->net_payable - $data['second_less'];
                }
                $admin_data['due_amount'] =   ($admin->due_amount - ($data['amount'] + $data['second_less']));
                $admin_data['advanced'] =   ($admin->advanced + $data['amount']);
                $admin_data['discount'] =   ($admin->discount + $data['second_less']);
                $admin_data['paid_status'] =  $admin_data['due_amount'] <= 0 ? 'paid' : 'unpaid';

                $this->billing->update('invoices', $admin_data, array('id' =>  $admin->id));

                $data['status'] = 1;
                $data['created_at'] = date('Y-m-d H:i:s');
                $data['created_by'] = $this->input->post('created_by') ?? logged_in_user_id();

                $insert_id = $this->billing->insert('invoice_payments', $data);

                if (has_permission(ADD, 'billing', 'billing_payment_sms')) {
                    send_sms('billing_payment_sms', $insert_id);
                }

                create_log('Has been created a payment : ' . $data['invoice_id']);
                $array = array('status' => 'success', 'error' => '', 'message' => $this->lang->line('insert_success'));
            } else {
                $array = array('status' => 'success', 'error' => '', 'message' => 'Please payment amount is less than or equal to the due amount.');
            }
        } else {
            $msg = array(
                'amount' => form_error('amount'),
            );
            $array = array('status' => 'failed', 'error' => $msg, 'message' => '');
        }

        echo json_encode($array);
    }

    public function payment_delete($id = null)
    {

        check_permission(DELETE);

        $invoice_payment = $this->billing->get_single('invoice_payments', array('id' => $id));

        if (!is_numeric($id)) {
            error($this->lang->line('unexpected_error'));
            redirect('billing/history/' . $invoice_payment->invoice_id);
        }

        if (!empty($invoice_payment)) {
            $invoice = $this->billing->get_single('invoices', array('id' => $invoice_payment->invoice_id));
            $this->billing->delete('invoice_payments', array('id' => $id));

            $invoice_data['advanced'] =  $invoice_payment->amount;
            $invoice_data['discount'] =  $invoice->discount + $invoice_payment->second_less;
            $invoice_data['due_amount'] =  $invoice->due_amount + $invoice_payment->amount;
            $invoice_data['paid_status'] =  'unpaid';

            $this->billing->update('invoices', $invoice_data, array('id' =>  $invoice->id));

            create_log('Has been deleted a invoice : ' . $invoice_payment->invoice_id . '-> [' . $invoice->custom_invoice_id . ']');
            success($this->lang->line('delete_success'));
        } else {
            error($this->lang->line('delete_failed'));
        }
        redirect($_SERVER['HTTP_REFERER']);
    }

    public function add_marketing()
    {
        if ($_POST) {
            $admin = $this->billing->get_single('invoices', array('id' => $this->input->post('invoice_id')));
            if (isset($admin) && $admin->id > 0) {
                $invoice_data['marketing_id'] =  $this->input->post('marketing_id') > 0 ? $this->input->post('marketing_id') : null;
                $invoice_data['note'] =  $this->input->post('note') ?? null;
                $this->billing->update('invoices', $invoice_data, array('id' =>  $admin->id));
                success($this->lang->line('update_success'));
                create_log('Has been added an invoice for marketing name : ' . $admin->id);
            }
        }
        redirect($_SERVER['HTTP_REFERER']);
    }

    public function add_ref()
    {
        check_permission(ADD);

        $invoice = $this->billing->get_single('invoices', array('id' => $this->input->post('add_reference_invoice_id')));
        if (!is_numeric($invoice->id)) {
            error($this->lang->line('unexpected_error'));
            redirect('billing/bill');
        }

        if ($_POST) {

            $this->load->library('form_validation');
            $this->form_validation->set_error_delimiters('<div class="error-message" style="color: red;">', '</div>');
            $this->form_validation->set_rules('add_reference_id', $this->lang->line('reference') . ' ' . $this->lang->line('name'), 'trim|required');

            if ($this->form_validation->run() === TRUE) {
                success($this->lang->line('update_success'));
                $invoice_details = $this->billing->get_list('invoice_details', array('invoice_id' => $invoice->id));
                $commission_amount = 0;
                foreach ($invoice_details as $item) {
                    $coms = $this->billing->get_single('employees', array('user_id' => $this->input->post('add_reference_id')));
                    $test_details = (array) $this->billing->get_single('diagnostic_tests', array('id' => $item->investagation_id));
                    if ($test_details) {
                        $commission_amount += ($item->total_rate - $test_details[$coms->commission_type]);
                    }
                }
                $invoice_data['commission_user_id'] =  $this->input->post('add_reference_id') ?? null;
                $invoice_data['note'] =  $this->input->post('note') ?? null;
                $invoice_data['commission_amount'] =  $commission_amount;
                $invoice_data['payable_commission'] =  ($commission_amount - $invoice->discount);
                $invoice_data['modified_by'] = logged_in_user_id();
                $this->billing->update('invoices', $invoice_data, array('id' =>  $invoice->id));


                // Insert DATA
                $insert_data['invoice_id'] = $invoice->id;
                $insert_data['commission_user_id'] = $this->input->post('add_reference_id');
                $insert_data['commission_amount'] = $commission_amount;
                $insert_data['payable_commission'] =  ($commission_amount - $invoice->discount);
                $insert_data['status'] = 1;
                $insert_data['created_at'] = date('Y-m-d H:i:s');
                $insert_data['created_by'] = logged_in_user_id();
                $this->billing->insert('invoice_reference_add_details', $insert_data);


                success($this->lang->line('success'));
                create_log('Has been added an invoice for reference name for billing : ' . $invoice->custom_invoice_id);
                $array = array('status' => 'success', 'error' => '', 'message' => $this->lang->line('update_success'));
            } else {
                $msg = array(
                    'add_reference_id' => form_error('add_reference_id'),
                );
                $array = array('status' => 'failed', 'error' => $msg, 'message' => '');
            }
            echo json_encode($array);
        }
    }
}
