<?php

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

class Estimates extends Admin_Controller
{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('estimates_model');
        $this->load->library('gst');

        // $this->load->helper('ckeditor');
    }

    private function get_estimate_sidebar_payload($mode, $selected_id = 0)
    {
        $allowed_modes = array('estimates_history', 'email_estimates');
        if (!in_array($mode, $allowed_modes, true)) {
            $mode = 'estimates_history';
        }

        $search = trim((string) $this->input->get('q', true));
        $page = (int) $this->input->get('page', true);
        $page = $page > 0 ? $page : 1;
        $per_page = 12;

        $total = (int) $this->estimates_model->count_estimate_sidebar($search);
        $pages = $total > 0 ? (int) ceil($total / $per_page) : 1;
        if ($page > $pages) {
            $page = $pages;
        }

        $offset = ($page - 1) * $per_page;

        return array(
            'estimate_sidebar_mode' => $mode,
            'estimate_sidebar_page' => $page,
            'estimate_sidebar_pages' => $pages,
            'estimate_sidebar_total' => $total,
            'estimate_sidebar_search' => $search,
            'estimate_sidebar_items' => $this->estimates_model->get_estimate_sidebar_page($per_page, $offset, $search),
            'estimate_sidebar_selected' => !empty($selected_id) ? $this->estimates_model->get_estimate_sidebar_estimate($selected_id) : null,
            'selected_estimate_id' => (int) $selected_id,
            'estimate_sidebar_page_url' => base_url('admin/estimates/create/' . $mode . '/' . (int) $selected_id),
        );
    }

    private function render_estimate_sidebar($mode, $selected_id = 0)
    {
        return $this->load->view('admin/estimates/_estimate_sidebar', $this->get_estimate_sidebar_payload($mode, $selected_id), true);
    }

    private function estimate_json_response($type, $message, $redirect_url = null, array $extra = array())
    {
        $payload = array_merge(array(
            'status' => $type,
            'message' => $message,
        ), $extra);
        if (!empty($redirect_url)) {
            $payload['url'] = $redirect_url;
        }
        $this->output->set_content_type('application/json');
        echo json_encode($payload);
        exit();
    }

    private function normalize_saved_item_tax_ids($raw_tax)
    {
        if ($raw_tax === null || $raw_tax === '') {
            return array();
        }
        $decoded = is_string($raw_tax) ? json_decode($raw_tax, true) : $raw_tax;
        if (json_last_error() !== JSON_ERROR_NONE || $decoded === null) {
            $decoded = $raw_tax;
        }
        $ids = array();
        $walk = function ($value) use (&$walk, &$ids) {
            if (is_array($value)) {
                foreach (array('tax_rates_id', 'id', 'value') as $key) {
                    if (isset($value[$key]) && is_numeric($value[$key])) {
                        $ids[] = (int) $value[$key];
                        return;
                    }
                }
                foreach ($value as $child) {
                    $walk($child);
                }
                return;
            }
            if (is_object($value)) {
                $walk((array) $value);
                return;
            }
            if (is_numeric($value)) {
                $ids[] = (int) $value;
            }
        };
        $walk($decoded);
        return array_values(array_unique(array_filter($ids)));
    }

    private function get_saved_item_tax_rows($raw_tax)
    {
        $tax_ids = $this->normalize_saved_item_tax_ids($raw_tax);
        if (empty($tax_ids)) {
            return array();
        }
        return $this->db->where_in('tax_rates_id', $tax_ids)->get('tbl_tax_rates')->result();
    }

    private function ensure_estimate_conversion_warehouse_stock($saved_items_id, $warehouse_id)
    {
        if (empty($saved_items_id) || empty($warehouse_id)) {
            return;
        }
        $exists = get_row('tbl_warehouses_products', array(
            'warehouse_id' => $warehouse_id,
            'product_id' => $saved_items_id,
        ));
        if (!empty($exists)) {
            return;
        }
        $item_info = get_row('tbl_saved_items', array('saved_items_id' => $saved_items_id));
        $quantity = !empty($item_info->quantity) ? (float) $item_info->quantity : 0;
        if ($quantity <= 0) {
            return;
        }
        $this->db->insert('tbl_warehouses_products', array(
            'warehouse_id' => $warehouse_id,
            'product_id' => $saved_items_id,
            'quantity' => $quantity,
        ));
    }


    public function index($action = NULL, $id = NULL, $item_id = NULL)
    {

        $data['page'] = lang('sales');
        $data['sub_active'] = lang('estimates');
        $data['datatable'] = true;

        // get permission user
        $data['permission_user'] = $this->estimates_model->all_permission_user('14');
        if ($action == 'estimates_details') {
            redirect('admin/estimates/estimates_details/' . $id);
        } elseif ($action == 'estimates_history') {
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['title'] = "Estimates History"; //Page title
            $subview = 'estimates_history';
        } elseif ($action == 'email_estimates') {
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['title'] = "Email Estimates"; //Page title
            $subview = 'email_estimates';
        } elseif ($action == 'pdf_estimates') {
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['title'] = "Estimates PDF"; //Page title
            $this->load->helper('dompdf');
            $viewfile = $this->load->view('admin/estimates/estimates_pdf', $data, TRUE);
            pdf_create($viewfile, slug_it('Estimates  # ' . $data['estimates_info']->reference_no));
        } else {
            $data['title'] = "Estimates"; //Page title
            $data['page_title'] = lang('estimates');
            $data['page_description'] = lang('estimate') . ' ' . lang('list');
            $subview = 'estimates';
            $this->estimates_model->_table_name = 'tbl_client';
            $this->estimates_model->_order_by = 'client_id';
            $data['all_client'] = $this->estimates_model->get();

            $estimateFilter = $this->estimates_model->get_estimate_filter();
            $status_filters = array();
            $period_filters = array();
            $year_filters = array();
            if (!empty($estimateFilter)) {
                foreach ($estimateFilter as $filter) {
                    $value = isset($filter['value']) ? $filter['value'] : '';
                    if (strpos($value, '_') === 0 && is_numeric(substr($value, 1))) {
                        $year_filters[] = $filter;
                    } elseif (in_array($value, array('last_month', 'this_months'), true)) {
                        $period_filters[] = $filter;
                    } else {
                        $status_filters[] = $filter;
                    }
                }
            }
            $status_options = array('' => lang('all') . ' ' . lang('status'));
            foreach ($status_filters as $filter) {
                $status_options[$filter['value']] = $filter['name'];
            }
            $period_options = array('' => lang('all') . ' ' . lang('estimate') . ' ' . lang('date'));
            foreach ($period_filters as $filter) {
                $period_options[$filter['value']] = $filter['name'];
            }
            $year_options = array('' => lang('all') . ' ' . lang('year'));
            foreach ($year_filters as $filter) {
                $year_options[$filter['value']] = $filter['name'];
            }

            if ($this->session->userdata('user_type') == 1) {
                $h_s = config_item('estimate_state');
                $estimate_quick_state_hidden = ($h_s == 'none');
                if ($estimate_quick_state_hidden) {
                    $title = lang('view_quick_state');
                    $url = 'show';
                    $icon = 'toggle-right';
                    $always_label = lang('quick_state') . ' ' . lang('always') . ': ' . lang('show');
                } else {
                    $title = lang('hide_quick_state');
                    $url = 'hide';
                    $icon = 'toggle-left';
                    $always_label = lang('quick_state') . ' ' . lang('always') . ': ' . lang('hide');
                }
                $data['header_actions'] = array();
                $data['header_actions_html'] = ''
                    . '<button type="button" id="quick_state" data-default-hidden="' . ($estimate_quick_state_hidden ? '1' : '0') . '"'
                    . ' title="' . html_escape($title) . '" data-tooltip="' . html_escape($title) . '" data-placement="top" aria-label="' . html_escape($title) . '"'
                    . ' aria-controls="state_report" aria-expanded="' . ($estimate_quick_state_hidden ? 'false' : 'true') . '"'
                    . ' class="inline-flex h-11 w-11 items-center justify-center rounded-xl border border-border bg-white text-slate-700 shadow-sm transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:bg-slate-800">'
                    . '<i data-lucide="' . ($estimate_quick_state_hidden ? 'panel-top-open' : 'panel-top-close') . '" class="h-4 w-4"></i>'
                    . '</button>';
                $data['header_actions_html'] .= ''
                    . '<a href="' . base_url('admin/dashboard/change_report/' . $url . '/estimate') . '"'
                    . ' data-no-instant-nav="1"'
                    . ' title="' . html_escape($always_label) . '" data-tooltip="' . html_escape($always_label) . '" data-placement="top" aria-label="' . html_escape($always_label) . '"'
                    . ' class="inline-flex h-11 w-11 items-center justify-center rounded-xl border border-amber-200 bg-amber-50 text-amber-700 shadow-sm transition hover:bg-amber-100 dark:border-amber-800/60 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/40">'
                    . '<i data-lucide="' . html_escape($icon) . '" class="h-4 w-4"></i>'
                    . '</a>';
            } else {
                $data['header_actions'] = array();
                $data['header_actions_html'] = '';
            }
            if (!empty(can_action('14', 'created')) || !empty(can_action('14', 'edited'))) {
                $data['header_actions'][] = array(
                    'label' => lang('create_estimate'),
                    'icon' => 'plus',
                    'href' => base_url('admin/estimates/create'),
                    'style' => 'primary',
                );
            }
            $data['header_actions_html'] .= btn_modal(
                'admin/invoice/zipped/estimate',
                '<span>' . lang('zip_estimate') . '</span>',
                lang('zip_estimate'),
                'md',
                'archive',
                array(
                    'class' => 'inline-flex items-center gap-2 rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-2.5 text-sm font-semibold text-emerald-700 hover:bg-emerald-100 dark:border-emerald-800/60 dark:bg-emerald-900/30 dark:text-emerald-300 dark:hover:bg-emerald-900/40',
                )
            );
            $estimate_filter_items = array(array('label' => lang('all'), 'active' => true, 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => 'all', 'data-estimate-search' => '', 'data-estimate-filter-label' => lang('all'))));
            foreach ($status_filters as $filter) {
                $estimate_filter_items[] = array('label' => $filter['name'], 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => $filter['value'], 'data-estimate-search' => '', 'data-estimate-filter-label' => $filter['name']));
            }
            foreach ($period_filters as $index => $filter) {
                $estimate_filter_items[] = array('label' => $filter['name'], 'divider_before' => $index === 0, 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => $filter['value'], 'data-estimate-search' => '', 'data-estimate-filter-label' => $filter['name']));
            }
            if (!empty($year_filters)) {
                $estimate_filter_items[] = array('label' => lang('year'), 'icon' => 'calendar-range', 'divider_before' => true, 'items' => array_map(function ($filter) {
                    return array('label' => $filter['name'], 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => $filter['value'], 'data-estimate-search' => '', 'data-estimate-filter-label' => $filter['name']));
                }, $year_filters));
            }
            $estimate_filter_items[] = array('label' => lang('project'), 'icon' => 'briefcase', 'divider_before' => true, 'items' => array(array('label' => lang('all') . ' ' . lang('project'), 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => '', 'data-estimate-search' => 'by_project', 'data-estimate-filter-label' => lang('all') . ' ' . lang('project')))), 'lookup' => array('endpoint' => base_url('admin/common/project_lookup'), 'limit' => 12, 'min_length' => 0, 'action_attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-search' => 'by_project'), 'filter_attr' => 'data-estimate-filter', 'label_attr' => 'data-estimate-filter-label', 'label_prefix' => lang('project') . ': ', 'placeholder' => lang('search') . ' ' . lang('project'), 'cache_key' => 'estimate_project_lookup'));
            $estimate_filter_items[] = array('label' => lang('client'), 'icon' => 'user', 'items' => array(array('label' => lang('all') . ' ' . lang('client'), 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => '', 'data-estimate-search' => 'by_client', 'data-estimate-filter-label' => lang('all') . ' ' . lang('client')))), 'lookup' => array('endpoint' => base_url('admin/common/client_lookup'), 'limit' => 12, 'min_length' => 0, 'action_attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-search' => 'by_client'), 'filter_attr' => 'data-estimate-filter', 'label_attr' => 'data-estimate-filter-label', 'label_prefix' => lang('client') . ': ', 'placeholder' => lang('search') . ' ' . lang('client'), 'cache_key' => 'estimate_client_lookup'));
            $estimate_filter_items[] = array('label' => lang('sales') . ' ' . lang('agent'), 'icon' => 'user-check', 'items' => array(array('label' => lang('all') . ' ' . lang('sales') . ' ' . lang('agent'), 'attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-filter' => '', 'data-estimate-search' => 'by_agent', 'data-estimate-filter-label' => lang('all') . ' ' . lang('sales') . ' ' . lang('agent')))), 'lookup' => array('endpoint' => base_url('admin/common/staff_lookup'), 'limit' => 12, 'min_length' => 0, 'action_attrs' => array('data-estimate-filter-action' => '1', 'data-estimate-search' => 'by_agent'), 'filter_attr' => 'data-estimate-filter', 'label_attr' => 'data-estimate-filter-label', 'label_prefix' => lang('sales') . ' ' . lang('agent') . ': ', 'placeholder' => lang('search') . ' ' . lang('sales') . ' ' . lang('agent'), 'cache_key' => 'estimate_staff_lookup'));
            $data['header_filters'] = array(array('label' => 'Filters', 'icon' => 'sliders-horizontal', 'selected_label' => lang('all'), 'attrs' => array('id' => 'estimate-header-filter'), 'items' => $estimate_filter_items));
            $data['header_filter_extras_html'] = '';
        }
        $data['active'] = 1;
        $data['subview'] = $this->load->view('admin/estimates/' . $subview, $data, TRUE);
        $this->load->view('admin/_layout_main', $data); //page load
    }

    final public function create($action = NULL, $id = NULL, $item_id = NULL)
    {
        $data['page'] = lang('sales');
        $data['sub_active'] = lang('estimates');
        if (!empty($item_id)) {
            $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
            if (!empty($can_edit)) {
                $data['item_info'] = $this->estimates_model->check_by(array('estimate_items_id' => $item_id), 'tbl_estimate_items');
            }
        }
        if ($action == 'edit_estimates') {
            $data['active'] = 2;
            $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
            if (!empty($can_edit)) {
                $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
                if (!empty($data['estimates_info']->client_id)) {
                    $data['estimate_to_merge'] = $this->estimates_model->check_for_merge_invoice($data['estimates_info']->client_id, $id);
                }
            }
        } else if ($action == 'project') {
            $data['project_id'] = $id;
            $data['project_info'] = $this->estimates_model->check_by(array('project_id' => $id), 'tbl_project');
            $data['active'] = 2;
        }
        if (!empty($action) && !is_numeric($action)) {
            $ex = explode('_', (string)$action);
            if (!empty($ex[0]) && $ex[0] === 'c' && !empty($ex[1]) && is_numeric($ex[1])) {
                $data['c_id'] = (int)$ex[1];
                $data['client_id'] = $data['c_id'];
                $client_row = $this->db->select('name')->where('client_id', $data['client_id'])->get('tbl_client')->row();
                $data['client_label'] = !empty($client_row->name) ? $client_row->name : '';
                $data['active'] = 2;
            }
        }
        if (!empty($item_id)) {
            $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
            if (!empty($can_edit)) {
                $data['item_info'] = $this->estimates_model->check_by(array('estimate_items_id' => $item_id), 'tbl_estimate_items');
            }
        }

        // get all client
        $this->estimates_model->_table_name = 'tbl_client';
        $this->estimates_model->_order_by = 'client_id';
        $data['all_client'] = $this->estimates_model->get();
        // get permission user
        $data['permission_user'] = $this->estimates_model->all_permission_user('14');
        $data['all_estimates_info'] = $this->estimates_model->get_permission('tbl_estimates');
        if ($action == 'estimates_details') {
            redirect('admin/estimates/estimates_details/' . $id);
            $data['title'] = "Estimates Details"; //Page title
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            if (empty($data['estimates_info'])) {
                $type = "error";
                $message = lang('no_record_found');
                set_message($type, $message);
                redirect('admin/estimates');
            }
            $subview = 'estimates_details';
        } elseif ($action == 'estimates_history') {
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['title'] = "Estimates History"; //Page title
            $data = array_merge($data, $this->get_estimate_sidebar_payload('estimates_history', $id));
            $data['estimate_sidebar_html'] = $this->render_estimate_sidebar('estimates_history', $id);
            $per_page = 20;
            $current_page = (int) $this->input->get('history_page', true);
            $current_page = $current_page > 0 ? $current_page : 1;
            $total_rows = $this->estimates_model->count_estimate_activities($id);
            $total_pages = max(1, (int) ceil($total_rows / $per_page));
            if ($current_page > $total_pages) {
                $current_page = $total_pages;
            }
            $offset = ($current_page - 1) * $per_page;
            $data['activities_info'] = $this->estimates_model->get_estimate_activity_page($id, $per_page, $offset);
            $data['history_page'] = $current_page;
            $data['history_pages'] = $total_pages;
            $data['history_total'] = $total_rows;
            $subview = 'estimates_history';
        } elseif ($action == 'email_estimates') {
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['title'] = "Email Estimates"; //Page title
            $data = array_merge($data, $this->get_estimate_sidebar_payload('email_estimates', $id));
            $data['estimate_sidebar_html'] = $this->render_estimate_sidebar('email_estimates', $id);
            $subview = 'email_estimates';
        } elseif ($action == 'pdf_estimates') {
            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['title'] = "Estimates PDF"; //Page title
            $this->load->helper('dompdf');
            $viewfile = $this->load->view('admin/estimates/estimates_pdf', $data, TRUE);
            pdf_create($viewfile, slug_it('Estimates  # ' . $data['estimates_info']->reference_no));
        } else {
            $data['title'] = "Estimates"; //Page title
            $subview = 'createestimates';
        }
        $data['active'] = 2;
        $data['subview'] = $this->load->view('admin/estimates/' . $subview, $data, TRUE);
        $this->load->view('admin/_layout_main', $data); //page load
    }

    public function estimates_details($id, $pdf = NULL)
    {
        $data['title'] = "Estimates"; //Page title
        $data['title'] = "Estimates"; //Page title
        $data['page_title'] = lang('estimate');
        $data['document_label'] = lang('estimate');
        $data['sales_info'] = join_data('tbl_estimates', '*', array('estimates_id' => $id), array('tbl_client' => 'tbl_client.client_id = tbl_estimates.client_id'));
        if (!empty($data['sales_info'])) {
            $data['sales_info']->ref_no = lang('estimates') . ' : ' . $data['sales_info']->reference_no;
            $data['sales_info']->start_date = lang('estimate_date') . ' : ' . display_date($data['sales_info']->estimate_date);
            $url = base_url('frontend/estimates/') . url_encode($id);
            $data['qrcode'] = generate_qrcode($url);
            // check overdue invoice
            if (safe_strtotime($data['sales_info']->due_date) < safe_strtotime(date('Y-m-d')) && $data['sales_info']->status == 'draft') {
                // check overdue how many days from due_date
                $date1 = new DateTime($data['sales_info']->due_date);
                $date2 = new DateTime(date('Y-m-d'));
                $interval = $date1->diff($date2);
                $overdue_days = $interval->format('%a');
                $data['sales_info']->overdue_days = lang('estimate_overdue') . ' ' . lang('by') . ' ' . $overdue_days . ' ' . lang('days');

            }
            $data['sales_info']->end_date = lang('due_date') . ' : ' . display_date($data['sales_info']->due_date);
            if (!empty($data['sales_info']->user_id)) {
                $data['sales_info']->sales_agent = lang('sales') . ' ' . lang('agent') . ' : ' . fullname($data['sales_info']->user_id);
            }
            $data['sales_info']->status_label = lang($data['sales_info']->status);
            $data['page_description'] = $data['sales_info']->reference_no;
            $status_key = strtolower((string) $data['sales_info']->status);
            $status_badges = array(
                'draft' => 'bg-slate-100 text-slate-700 border-slate-200',
                'sent' => 'bg-blue-50 text-blue-700 border-blue-200',
                'declined' => 'bg-rose-50 text-rose-700 border-rose-200',
                'accepted' => 'bg-emerald-50 text-emerald-700 border-emerald-200',
                'expired' => 'bg-amber-50 text-amber-700 border-amber-200',
            );
            $status_class = isset($status_badges[$status_key]) ? $status_badges[$status_key] : 'bg-slate-100 text-slate-700 border-slate-200';
            $data['header_badge_html'] = '<span class="inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold ' . $status_class . '">' . html_escape($data['sales_info']->status_label) . '</span>';
            $data['notified_reminder'] = (int) $this->db
                ->where(array('module' => 'estimate', 'module_id' => $data['sales_info']->estimates_id, 'notified' => 'No'))
                ->count_all_results('tbl_reminders');
            $data['header_actions'] = array();
            if (!empty(can_action('14', 'edited'))) {
                $data['header_actions'][] = array(
                    'label' => lang('edit'),
                    'icon' => 'pencil',
                    'href' => base_url('admin/estimates/create/edit_estimates/' . $data['sales_info']->estimates_id),
                    'style' => 'info',
                );
            }
            $data['header_actions_html'] = '';
            if (!empty(can_action('14', 'edited'))) {
                $data['header_actions_html'] .= btn_modal(
                    'admin/estimates/insert_items/' . $data['sales_info']->estimates_id,
                    '<span>' . lang('add_items') . '</span>',
                    lang('add_items'),
                    'md',
                    'plus',
                    array(
                        'class' => 'inline-flex items-center gap-2 rounded-xl border border-violet-600 bg-violet-600 px-3 py-1.5 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-violet-500 dark:border-violet-500 dark:bg-violet-500 dark:hover:bg-violet-400',
                    )
                );
                $data['header_actions_html'] .= btn_modal(
                    'admin/estimates/convert_to_invoice/' . $data['sales_info']->estimates_id,
                    '<span>' . lang('convert_to_invoice') . '</span>',
                    lang('convert_to_invoice'),
                    'xl',
                    'repeat',
                    array(
                        'class' => 'inline-flex items-center gap-2 rounded-xl border border-violet-600 bg-violet-600 px-3 py-1.5 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-violet-500 dark:border-violet-500 dark:bg-violet-500 dark:hover:bg-violet-400',
                    )
                );
            }
            $data['header_actions_html'] .= btn_modal(
                'admin/invoice/reminder/estimate/' . $data['sales_info']->estimates_id,
                '<span>' . lang('reminder') . '</span>',
                lang('reminder'),
                'lg',
                'bell',
                array(
                    'class' => 'inline-flex items-center gap-2 rounded-xl border border-amber-200 bg-amber-50 px-3 py-1.5 text-sm font-semibold text-amber-700 shadow-sm transition-colors hover:bg-amber-100 dark:border-amber-800 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/40',
                )
            );
            if (!empty(can_action('14', 'edited'))) {
                $more_actions = '<div class="relative" data-dropdown style="position:relative;">';
                $more_actions .= '<button type="button" data-dropdown-toggle="estimate-actions" class="inline-flex h-11 items-center gap-2 rounded-xl border border-border bg-white px-4 text-sm font-semibold text-slate-700 shadow-sm transition-colors hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:bg-slate-800" title="' . html_escape(lang('more_actions')) . '" aria-label="' . html_escape(lang('more_actions')) . '"><i data-lucide="more-horizontal" class="h-4 w-4"></i><span>' . html_escape(lang('more_actions')) . '</span></button>';
                $more_actions .= '<div id="estimate-actions" data-dropdown-menu class="hidden absolute right-0 mt-2 w-56 max-w-[calc(100vw-1rem)] max-h-[calc(100vh-6rem)] overflow-y-auto rounded-xl border border-border bg-card p-2 shadow-lg z-30">';
                $more_actions .= '<a href="' . base_url('admin/estimates/index/pdf_estimates/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="download" class="h-3.5 w-3.5 text-blue-500"></i><span>PDF</span></a>';
                $more_actions .= '<a href="' . base_url('admin/estimates/send_estimates_email/' . $data['sales_info']->estimates_id . '/' . true) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="mail" class="h-3.5 w-3.5 text-emerald-500"></i><span>' . html_escape(lang('send_email')) . '</span></a>';
                $more_actions .= '<a href="#" onclick="print_sales_details(\'sales_details\'); return false;" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="printer" class="h-3.5 w-3.5 text-slate-500"></i><span>' . html_escape(lang('print')) . '</span></a>';
                $more_actions .= btn_modal(
                    'admin/estimates/clone_estimate/' . $data['sales_info']->estimates_id,
                    '<span>' . lang('clone') . '</span>',
                    lang('clone') . ' ' . lang('estimate'),
                    'md',
                    'copy',
                    array(
                        'class' => 'flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted',
                    )
                );
                $more_actions .= '<div class="my-2 border-t border-border"></div>';
                $more_actions .= '<a href="' . base_url('admin/estimates/create/email_estimates/' . $data['sales_info']->estimates_id) . '" data-toggle="ajaxModal" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="send" class="h-3.5 w-3.5 text-sky-500"></i><span>' . html_escape(lang('email_estimate')) . '</span></a>';
                $more_actions .= '<a href="' . base_url('admin/estimates/create/estimates_history/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="history" class="h-3.5 w-3.5 text-slate-500"></i><span>' . html_escape(lang('estimate_history')) . '</span></a>';
                $more_actions .= '<div class="my-2 border-t border-border"></div>';
                if (in_array($data['sales_info']->status, array('expired', 'sent', 'cancelled', 'draft'), true)) {
                    $more_actions .= '<a href="' . base_url('admin/estimates/change_status/pending/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="clock-3" class="h-3.5 w-3.5 text-amber-500"></i><span>' . html_escape(lang('mark_as_pending')) . '</span></a>';
                }
                if ($data['sales_info']->status == 'draft') {
                    $more_actions .= '<a href="' . base_url('admin/estimates/change_status/draft/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="file-text" class="h-3.5 w-3.5 text-slate-500"></i><span>' . html_escape(lang('mark_as_draft')) . '</span></a>';
                }
                if ($data['sales_info']->status != 'sent' || $data['sales_info']->status == 'expired') {
                    $more_actions .= '<a href="' . base_url('admin/estimates/change_status/sent/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="send" class="h-3.5 w-3.5 text-sky-500"></i><span>' . html_escape(lang('mark_as_sent')) . '</span></a>';
                }
                if (in_array($data['sales_info']->status, array('pending', 'sent'), true)) {
                    $more_actions .= '<a href="' . base_url('admin/estimates/change_status/expired/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="calendar-x" class="h-3.5 w-3.5 text-amber-500"></i><span>' . html_escape(lang('mark_as_expired')) . '</span></a>';
                }
                if ($data['sales_info']->status != 'cancelled') {
                    $more_actions .= '<a href="' . base_url('admin/estimates/change_status/cancelled/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="ban" class="h-3.5 w-3.5 text-rose-500"></i><span>' . html_escape(lang('mark_as_cancelled')) . '</span></a>';
                } else {
                    $more_actions .= '<a href="' . base_url('admin/estimates/change_status/draft/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="undo-2" class="h-3.5 w-3.5 text-slate-500"></i><span>' . html_escape(lang('unmark_as_cancelled')) . '</span></a>';
                }
                $more_actions .= '<a href="' . base_url('admin/estimates/change_status/declined/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="x-circle" class="h-3.5 w-3.5 text-rose-500"></i><span>' . html_escape(lang('declined')) . '</span></a>';
                $more_actions .= '<a href="' . base_url('admin/estimates/change_status/accepted/' . $data['sales_info']->estimates_id) . '" class="flex items-center gap-2 rounded-lg px-3 py-2 text-xs text-foreground transition-colors hover:bg-muted"><i data-lucide="check-circle-2" class="h-3.5 w-3.5 text-emerald-500"></i><span>' . html_escape(lang('accepted')) . '</span></a>';
                $more_actions .= '</div></div>';
                $data['header_actions_html'] .= $more_actions;
            }
            $data['sales_info']->custom_field = '';
            $show_custom_fields = custom_form_label(10, $data['sales_info']->estimates_id);
            if (!empty($show_custom_fields)) {
                foreach ($show_custom_fields as $c_label => $v_fields) {
                    if (!empty($v_fields)) {
                        $data['sales_info']->custom_field .= $c_label . ' : ' . $v_fields . '<br>';
                    }
                }
            }
            $data['items_id'] = 'estimate_items_id';
            $data['all_items'] = $this->estimates_model->ordered_items_by_id($data['sales_info']->estimates_id);
            $data['sales_info']->sub_total = ($this->estimates_model->estimate_calculation('estimate_cost', $data['sales_info']->estimates_id));
            $data['sales_info']->discount = ($this->estimates_model->estimate_calculation('discount', $data['sales_info']->estimates_id));
            $data['sales_info']->total = ($this->estimates_model->estimate_calculation('total', $data['sales_info']->estimates_id));
            // get payment info by id
            $data['footer'] = config_item('estimate_footer');
        } else {
            set_message('error', lang('no_data_found'));
            redirect('admin/estimates');
        }
        if (!empty($pdf)) {
            return $this->common_model->sales_pdf($data, $pdf);
        }
        $data['estimate_pdf_print_html'] = $this->load->view('admin/common/sales_pdf', $data, TRUE);
        $data['subview'] = $this->load->view('admin/estimates/estimates_details', $data, TRUE);
        $this->load->view('admin/_layout_main', $data); //page load

    }


    public function estimates_state_report()
    {
        if (!$this->input->is_ajax_request()) {
            redirect('admin/dashboard');
        }
        $data = array();
        $pathonor_jonno['estimates_state_report_div'] = $this->load->view("admin/estimates/estimates_state_report", $data, true);
        echo json_encode($pathonor_jonno);
        exit;
    }


    public function estimatesList($filterBy = null, $search_by = null)
    {
        if ($this->input->is_ajax_request()) {
            $edited = can_action('14', 'edited');
            $deleted = can_action('14', 'deleted');
            $this->load->model('datatables');
            $this->datatables->table = 'tbl_estimates';
            $this->datatables->join_table = array('tbl_client');
            $this->datatables->join_where = array('tbl_estimates.client_id=tbl_client.client_id');
            $this->datatables->select = 'tbl_estimates.*,tbl_client.name';
            $this->datatables->column_order = array('reference_no', 'tbl_client.name', 'estimate_date', 'due_date', 'status', 'tags');
            $this->datatables->column_search = array('reference_no', 'tbl_client.name', 'estimate_date', 'due_date', 'status', 'tags');
            $this->datatables->order = array('estimates_id' => 'desc');

            if (!empty($edited) && !empty($deleted)) {
                if (empty($filterBy)) {
                    $filterBy = '_' . date('Y');
                }
            }
            if (!empty($filterBy) && !is_numeric($filterBy)) {
                $ex = explode('_', $filterBy);
                if ($ex[0] != 'c') {
                    $filterBy = $filterBy;
                }
            }
            $where = array();
            $where_in = null;
            if (!empty($search_by)) {
                if ($search_by == 'by_project') {
                    $where = array('project_id' => $filterBy);
                }
                if ($search_by == 'by_agent') {
                    $where = array('user_id' => $filterBy);
                }
                if ($search_by == 'by_client') {
                    $where = array('tbl_estimates.client_id' => $filterBy);
                }
            } else {
                if ($filterBy == 'last_month' || $filterBy == 'this_months') {
                    if ($filterBy == 'last_month') {
                        $month = date('Y-m', safe_strtotime('-1 months'));
                    } else {
                        $month = date('Y-m');
                    }
                    $where = array('estimate_month' => $month);
                } else if ($filterBy == 'expired') {
                    $where = array('UNIX_TIMESTAMP(due_date) <' => safe_strtotime(date('Y-m-d')));
                    $status = array('draft', 'pending');
                    $where_in = array('status', $status);
                } else if (strstr($filterBy, '_')) {
                    $year = str_replace('_', '', $filterBy);
                    $where = array('estimate_year' => $year);
                } else if (!empty($filterBy) && $filterBy != 'all') {
                    $where = array('status' => $filterBy);
                }
            }
            // get all estimate
            $fetch_data = $this->datatables->get_datatable_permission($where);

            $data = array();


            foreach ($fetch_data as $_key => $v_estimates) {
                if (!empty($v_estimates)) {
                    $action = null;
                    $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $v_estimates->estimates_id));
                    $can_delete = $this->estimates_model->can_action('tbl_estimates', 'delete', array('estimates_id' => $v_estimates->estimates_id));

                    if ($v_estimates->status == 'pending') {
                        $label = "info";
                    } elseif ($v_estimates->status == 'accepted') {
                        $label = "success";
                    } else {
                        $label = "danger";
                    }

                    $sub_array = array();
                    $name = null;
                    $name .= '<a class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300" href="' . base_url() . 'admin/estimates/create/estimates_details/' . $v_estimates->estimates_id . '">' . $v_estimates->reference_no . '</a>';
                    if ($v_estimates->invoiced == 'Yes') {
                        $invoice_info = $this->db->where('invoices_id', $v_estimates->invoices_id)->get('tbl_invoices')->row();
                        if (!empty($invoice_info)) {
                            $name .= '<p class="text-sm m0 p0"><a class="text-success" href="' . base_url() . 'admin/invoice/manage_invoice/invoice_details/' . $invoice_info->invoices_id . '">' . lang('invoiced') . '</a></p>';
                        }
                    }
                    $sub_array[] = $name;
                    $sub_array[] = display_date($v_estimates->estimate_date);
                    $overdue = null;
                    if (safe_strtotime($v_estimates->due_date) < safe_strtotime(date('Y-m-d')) && $v_estimates->status == 'pending' || safe_strtotime($v_estimates->due_date) < safe_strtotime(date('Y-m-d')) && $v_estimates->status == ('draft')) {
                        $overdue .= '<span class="label label-danger ">' . lang("expired") . '</span>';
                    }
                    $sub_array[] = display_date($v_estimates->due_date) . ' ' . $overdue;

                    $sub_array[] = '<span class="tags">' . client_name($v_estimates->client_id) . '</span>';

                    $sub_array[] = display_money($this->estimates_model->estimate_calculation('total', $v_estimates->estimates_id), client_currency($v_estimates->client_id));
                    $sub_array[] = "<span class='tags label label-" . $label . "'>" . lang($v_estimates->status) . "</span>";

                    $sub_array[] = get_tags($v_estimates->tags, true);

                    $custom_form_table = custom_form_table(10, $v_estimates->estimates_id);

                    if (!empty($custom_form_table)) {
                        foreach ($custom_form_table as $c_label => $v_fields) {
                            $sub_array[] = $v_fields;
                        }
                    }
                    if (!empty($can_edit) && !empty($edited)) {
                        $action .= btn_modal(
                            'admin/estimates/clone_estimate/' . $v_estimates->estimates_id,
                            '',
                            lang('clone') . ' ' . lang('estimate'),
                            'md',
                            'copy',
                            array('class' => 'inline-flex items-center gap-1.5 rounded-lg border border-sky-200 bg-sky-100 px-2 py-1 text-xs font-semibold text-sky-700 hover:bg-sky-200 dark:border-sky-800 dark:bg-sky-900/40 dark:text-sky-300 dark:hover:bg-sky-900/60')
                        ) . ' ';
                        $action .= btn_edit('admin/estimates/create/edit_estimates/' . $v_estimates->estimates_id) . ' ';
                    }
                    if (!empty($can_delete) && !empty($deleted)) {
                        $action .= ajax_anchor(base_url("admin/estimates/delete/delete_estimates/$v_estimates->estimates_id"), '', array("class" => "inline-flex h-7 items-center rounded-md border border-rose-200 bg-rose-50 px-2 py-1 text-xs font-semibold text-rose-700 hover:bg-rose-100 dark:border-rose-800 dark:bg-rose-900/20 dark:text-rose-300 dark:hover:bg-rose-900/40", "title" => lang('delete'), "data-fade-out-on-success" => "#table_" . $_key)) . ' ';
                    }
                    $change_status = null;
                    if (!empty($can_edit) && !empty($edited)) {
                        $ch_url = base_url() . 'admin/estimates/';
                        $change_status .= '<details class="relative inline-flex">
						<summary class="inline-flex h-8 items-center gap-1 rounded-lg border border-slate-300 bg-white px-2.5 py-1 text-xs font-medium text-slate-700 shadow-sm hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-200 dark:hover:bg-slate-700 cursor-pointer list-none"> <i data-lucide="settings" class="h-4 w-4"></i>
                    ' . lang('change') . '
            			</summary>
						<ul class="absolute right-0 z-20 mt-2 min-w-[170px] overflow-hidden rounded-xl border border-slate-200 bg-white text-xs shadow-lg dark:border-slate-700 dark:bg-slate-900">';
                        $change_status .= '<li><a class="block px-3 py-2 text-slate-700 hover:bg-slate-50 dark:text-slate-200 dark:hover:bg-slate-800" href="' . $ch_url . 'index/estimates_details/' . $v_estimates->estimates_id . '">' . lang('preview') . '</a></li>';
                        $change_status .= '<li><a class="block px-3 py-2 text-slate-700 hover:bg-slate-50 dark:text-slate-200 dark:hover:bg-slate-800" href="' . $ch_url . 'index/email_estimates/' . $v_estimates->estimates_id . '">' . lang('send_email') . '</a></li>';
                        $change_status .= '<li><a class="block px-3 py-2 text-slate-700 hover:bg-slate-50 dark:text-slate-200 dark:hover:bg-slate-800" href="' . $ch_url . 'index/estimates_history/' . $v_estimates->estimates_id . '">' . lang('history') . '</a></li>';
                        $change_status .= '<li><a class="block px-3 py-2 text-slate-700 hover:bg-slate-50 dark:text-slate-200 dark:hover:bg-slate-800" href="' . $ch_url . 'change_status/declined/' . $v_estimates->estimates_id . '">' . lang('declined') . '</a></li>';
                        $change_status .= '<li><a class="block px-3 py-2 text-slate-700 hover:bg-slate-50 dark:text-slate-200 dark:hover:bg-slate-800" href="' . $ch_url . 'change_status/accepted/' . $v_estimates->estimates_id . '">' . lang('accepted') . '</a></li>';
                        $change_status .= '</ul></details>';
                        $action .= $change_status;
                    }

                    $sub_array[] = '<div class="erp-table-actions">' . $action . '</div>';
                    $data[] = $sub_array;
                }
            }
            render_table($data, $where, $where_in);
        } else {
            redirect('admin/dashboard');
        }
    }

    public
    function client_change_data($customer_id, $current_invoice = 'undefined')
    {
        if ($this->input->is_ajax_request()) {
            $data = array();
            $data['client_currency'] = $this->estimates_model->client_currency_symbol($customer_id);
            $_data['estimate_to_merge'] = $this->estimates_model->check_for_merge_invoice($customer_id, $current_invoice);
            $data['merge_info'] = $this->load->view('admin/estimates/merge_estimate', $_data, true);
            echo json_encode($data);
            exit();
        }
    }

    public
    function get_merge_data($id)
    {
        $invoice_items = $this->estimates_model->ordered_items_by_id($id);
        $i = 0;
        foreach ($invoice_items as $item) {
            $invoice_items[$i]->taxname = $this->estimates_model->get_invoice_item_taxes($item->estimate_items_id);
            $invoice_items[$i]->qty = $item->quantity;
            $invoice_items[$i]->rate = $item->unit_cost;
            $i++;
        }
        echo json_encode($invoice_items);
        exit();
    }

    public
    function pdf_estimates($id)
    {
        $this->estimates_details($id, true);
    }

    public
    function save_estimates($id = NULL)
    {
        $created = can_action('14', 'created');
        $edited = can_action('14', 'edited');
        if (!empty($created) || !empty($edited) && !empty($id)) {
            $data = $this->estimates_model->array_from_post(array('reference_no', 'client_id', 'project_id', 'discount_type', 'tags', 'discount_percent', 'user_id', 'adjustment', 'discount_total', 'show_quantity_as'));
            $data['tags'] = normalize_and_sync_tags($data['tags']);
            $data['show_quantity_as'] = strtolower((string) $data['show_quantity_as']);
            if (!in_array($data['show_quantity_as'], array('qty', 'hours', 'qty_hours'), true)) {
                $data['show_quantity_as'] = 'qty';
            }
            if (empty($data['project_id'])) {
                $data['project_id'] = 0;
            }
            if (empty($data['discount_type'])) {
                $data['discount_type'] = 'none';
            }

            $data['client_visible'] = ($this->input->post('client_visible') == 'Yes') ? 'Yes' : 'No';
            $data['estimate_date'] = date('Y-m-d', safe_strtotime($this->input->post('estimate_date', TRUE)));
            if (empty($data['estimate_date'])) {
                $data['estimate_date'] = date('Y-m-d');
            }
            $data['warehouse_id'] = $this->input->post('warehouse_id', TRUE);
            $data['estimate_year'] = date('Y', safe_strtotime($this->input->post('estimate_date', TRUE)));
            $data['estimate_month'] = date('Y-m', safe_strtotime($this->input->post('estimate_date', TRUE)));
            $data['due_date'] = date('Y-m-d', safe_strtotime($this->input->post('due_date', TRUE)));
            $data['notes'] = $this->input->post('notes', TRUE);
            $tax['tax_name'] = $this->input->post('total_tax_name', TRUE);
            $tax['total_tax'] = $this->input->post('total_tax', TRUE);
            $data['total_tax'] = json_encode($tax);
            $i_tax = 0;
            if (!empty($tax['total_tax'])) {
                foreach ($tax['total_tax'] as $v_tax) {
                    $i_tax += $v_tax;
                }
            }
            $data['tax'] = $i_tax;
            $save_as_draft = $this->input->post('status', TRUE);
            if (!empty($save_as_draft)) {
                $data['status'] = $save_as_draft;
            } else {
                $data['status'] = 'pending';
            }

            $currency = $this->estimates_model->client_currency_symbol($data['client_id']);
            if (!empty($currency->code)) {
                $curren = $currency->code;
            } else {
                $curren = config_item('default_currency');
            }
            $data['currency'] = $curren;

            $permission = $this->input->post('permission', true);
            if (!empty($permission)) {
                if ($permission == 'everyone') {
                    $assigned = 'all';
                } else {
                    $assigned_to = $this->estimates_model->array_from_post(array('assigned_to'));
                    if (!empty($assigned_to['assigned_to'])) {
                        foreach ($assigned_to['assigned_to'] as $assign_user) {
                            $assigned[$assign_user] = $this->input->post('action_' . $assign_user, true);
                        }
                    }
                }
                if (!empty($assigned)) {
                    if ($assigned != 'all') {
                        $assigned = json_encode($assigned);
                    }
                } else {
                    $assigned = 'all';
                }
                $data['permission'] = $assigned;
            } else {
                set_message('error', lang('assigned_to') . ' Field is required');
                if (empty($_SERVER['HTTP_REFERER'])) {
                    redirect('admin/estimates');
                } else {
                    redirect($_SERVER['HTTP_REFERER']);
                }
            }

            // get all client
            $this->estimates_model->_table_name = 'tbl_estimates';
            $this->estimates_model->_primary_key = 'estimates_id';
            if (!empty($id)) {
                $estimates_id = $id;
                $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
                if (!empty($can_edit)) {
                    $this->estimates_model->save($data, $id);
                } else {
                    set_message('error', lang('there_in_no_value'));
                    redirect('admin/estimates');
                }
                $action = ('activity_estimates_updated');
                $msg = lang('estimate_updated');
                $description = 'not_estimate_updated';
            } else {
                $estimates_id = $this->estimates_model->save($data);
                $action = ('activity_estimates_created');
                $description = 'not_estimate_created';
                $msg = lang('estimate_created');
            }
            save_custom_field(10, $estimates_id);

            // save items
            $invoices_to_merge = $this->input->post('invoices_to_merge', TRUE);
            $cancel_merged_invoices = $this->input->post('cancel_merged_estimate', TRUE);
            if (!empty($invoices_to_merge)) {
                foreach ($invoices_to_merge as $inv_id) {
                    if (empty($cancel_merged_invoices)) {
                        $this->db->where('estimates_id', $inv_id);
                        $this->db->delete('tbl_estimates');

                        $this->db->where('estimates_id', $inv_id);
                        $this->db->delete('tbl_estimate_items');
                    } else {
                        $mdata = array('status' => 'cancelled');
                        $this->estimates_model->_table_name = 'tbl_estimates';
                        $this->estimates_model->_primary_key = 'estimates_id';
                        $this->estimates_model->save($mdata, $inv_id);
                    }
                }
            }

            $removed_items = $this->input->post('removed_items', TRUE);
            if (!empty($removed_items)) {
                foreach ($removed_items as $r_id) {
                    if ($r_id != 'undefined') {
                        $this->db->where('estimate_items_id', $r_id);
                        $this->db->delete('tbl_estimate_items');
                    }
                }
            }

            $itemsid = $this->input->post('estimate_items_id', TRUE);
            $items_data = $this->input->post('items', true);

            if (!empty($items_data)) {
                $index = 0;
                foreach ($items_data as $items) {
                    $items['estimates_id'] = $estimates_id;
                    $items_id = null;
                    if (!empty($items['items_id']) && $items['items_id'] != 'undefined') {
                        $items_id = $items['items_id'];
                    } elseif (!empty($items['estimate_items_id']) && $items['estimate_items_id'] != 'undefined') {
                        $items_id = $items['estimate_items_id'];
                    }

                    unset($items['items_id']);
                    unset($items['estimate_items_id']);
                    unset($items['invoice_items_id']);
                    unset($items['credit_note_items_id']);
                    unset($items['proposals_items_id']);
                    unset($items['total_qty']);
                    $tax = 0;
                    if (!empty($items['taxname'])) {
                        foreach ($items['taxname'] as $tax_name) {
                            $tax_rate = explode("|", $tax_name);
                            $tax += $tax_rate[1];
                        }
                        $items['item_tax_name'] = $items['taxname'];
                        unset($items['taxname']);
                        $items['item_tax_name'] = json_encode($items['item_tax_name']);
                    }
                    if (empty($items['saved_items_id']) || $items['saved_items_id'] == 'undefined') {
                        $items['saved_items_id'] = 0;
                    }


                    $price = $items['quantity'] * $items['unit_cost'];
                    $items['item_tax_total'] = ($price / 100 * $tax);
                    $items['total_cost'] = $price;
                    // get all client
                    $this->estimates_model->_table_name = 'tbl_estimate_items';
                    $this->estimates_model->_primary_key = 'estimate_items_id';

                    if (!empty($items_id)) {
                        $this->estimates_model->save($items, $items_id);
                    } else {
                        $items_id = $this->estimates_model->save($items);
                    }
                    $index++;
                }
            }
            $activity = array(
                'user' => $this->session->userdata('user_id'),
                'module' => 'estimates',
                'module_field_id' => $estimates_id,
                'activity' => $action,
                'icon' => 'fa-shopping-cart',
                'link' => 'admin/estimates/create/estimates_details/' . $estimates_id,
                'value1' => $data['reference_no']
            );
            $this->estimates_model->_table_name = 'tbl_activities';
            $this->estimates_model->_primary_key = 'activities_id';
            $this->estimates_model->save($activity);

            // send notification to client
            if (!empty($data['client_id'])) {
                $client_info = $this->estimates_model->check_by(array('client_id' => $data['client_id']), 'tbl_client');
                if (!empty($client_info->primary_contact)) {
                    $notifyUser = array($client_info->primary_contact);
                } else {
                    $user_info = $this->estimates_model->check_by(array('company' => $data['client_id']), 'tbl_account_details');
                    if (!empty($user_info)) {
                        $notifyUser = array($user_info->user_id);
                    }
                }
            }
            if (!empty($notifyUser)) {
                foreach ($notifyUser as $v_user) {
                    if ($v_user != $this->session->userdata('user_id')) {
                        add_notification(array(
                            'to_user_id' => $v_user,
                            'icon' => 'shopping-cart',
                            'description' => $description,
                            'link' => 'client/estimates/index/estimates_details/' . $estimates_id,
                            'value' => $data['reference_no'],
                        ));
                    }
                }
                show_notification($notifyUser);
            }

            // messages for user
            $type = "success";
            $message = $msg;
            set_message($type, $message);
        }
        if (!empty($data['project_id']) && is_numeric($data['project_id'])) {
            redirect('admin/projects/project_details/' . $data['project_id']);
        } else {
            redirect('admin/estimates/create/estimates_details/' . $estimates_id);
        }
        redirect('admin/estimates');
    }

    public
    function insert_items($estimates_id)
    {
        $edited = can_action('14', 'edited');
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $estimates_id));
        if (!empty($can_edit) && !empty($edited) && !empty($estimates_id)) {
            $data['estimates_id'] = $estimates_id;
            $data['modal_subview'] = $this->load->view('admin/estimates/_modal_insert_items', $data, FALSE);
        } else {
            set_message('error', lang('there_in_no_value'));
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }
    }

    public
    function add_insert_items($estimates_id)
    {
        $is_ajax = $this->input->is_ajax_request();
        $redirect_url = 'admin/estimates/create/estimates_details/' . $estimates_id;
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $estimates_id));
        $edited = can_action('14', 'edited');
        if (!empty($can_edit) && !empty($edited)) {
            $saved_items_id = $this->input->post('saved_items_id', TRUE);
            if (!empty($saved_items_id)) {
                $inserted_items = 0;
                $saved_items_id = array_values(array_unique(array_filter((array) $saved_items_id)));
                foreach ($saved_items_id as $v_items_id) {
                    $items_info = $this->estimates_model->check_by(array('saved_items_id' => $v_items_id), 'tbl_saved_items');
                    if (empty($items_info)) {
                        continue;
                    }
                    $tax_info = $this->get_saved_item_tax_rows($items_info->tax_rates_id);
                    $tax_name = array();
                    $tax_total = 0;
                    if (!empty($tax_info)) {
                        foreach ($tax_info as $v_tax) {
                            $tax_name[] = $v_tax->tax_rate_name . '|' . $v_tax->tax_rate_percent;
                            $tax_total += ((float) $items_info->unit_cost / 100) * (float) $v_tax->tax_rate_percent;
                        }
                    }
                    if (!empty($tax_name)) {
                        $tax_name = $tax_name;
                    } else {
                        $tax_name = array();
                    }

                    $existing_items = $this->db
                        ->where('estimates_id', $estimates_id)
                        ->where('saved_items_id', $items_info->saved_items_id)
                        ->order_by('estimate_items_id', 'ASC')
                        ->get('tbl_estimate_items')
                        ->result();
                    $existing_quantity = 0;
                    if (!empty($existing_items)) {
                        foreach ($existing_items as $existing_item) {
                            $existing_quantity += (float) $existing_item->quantity;
                        }
                    }
                    $quantity = !empty($existing_items) ? ($existing_quantity + 1) : 1;
                    $line_subtotal = (float) $items_info->unit_cost * $quantity;

                    $data = array();
                    $data['quantity'] = $quantity;
                    $data['estimates_id'] = $estimates_id;
                    $data['saved_items_id'] = $items_info->saved_items_id;
                    $data['item_name'] = $items_info->item_name;
                    $data['item_desc'] = $items_info->item_desc;
                    $data['hsn_code'] = $items_info->hsn_code;
                    $data['unit_cost'] = $items_info->unit_cost;
                    $data['item_tax_rate'] = '0.00';
                    $data['item_tax_name'] = json_encode($tax_name);
                    $data['item_tax_total'] = $tax_total * $quantity;
                    $data['total_cost'] = $line_subtotal;

                    $this->estimates_model->_table_name = 'tbl_estimate_items';
                    $this->estimates_model->_primary_key = 'estimate_items_id';
                    if (!empty($existing_items)) {
                        $items_id = $existing_items[0]->estimate_items_id;
                        $this->estimates_model->save($data, $items_id);
                        if (count($existing_items) > 1) {
                            $duplicate_ids = array();
                            foreach (array_slice($existing_items, 1) as $duplicate_item) {
                                $duplicate_ids[] = $duplicate_item->estimate_items_id;
                            }
                            if (!empty($duplicate_ids)) {
                                $this->db->where_in('estimate_items_id', $duplicate_ids)->delete('tbl_estimate_items');
                            }
                        }
                        $action = 'activity_estimates_items_updated';
                    } else {
                        $items_id = $this->estimates_model->save($data);
                        $action = 'activity_estimates_items_added';
                    }
                    $inserted_items++;
                    $msg = lang('estimate_item_save');
                    $activity = array(
                        'user' => $this->session->userdata('user_id'),
                        'module' => 'estimates',
                        'module_field_id' => $items_id,
                        'activity' => $action,
                        'icon' => 'fa-shopping-cart',
                        'link' => 'admin/estimates/create/estimates_details/' . $estimates_id,
                        'value1' => $items_info->item_name
                    );
                    $this->estimates_model->_table_name = 'tbl_activities';
                    $this->estimates_model->_primary_key = 'activities_id';
                    $this->estimates_model->save($activity);
                }
                if ($inserted_items > 0) {
                    $type = "success";
                    $this->update_invoice_tax($saved_items_id, $estimates_id);
                } else {
                    $type = "error";
                    $msg = lang('no_record_found') ?: 'No valid items were found.';
                }
            } else {
                $type = "error";
                $msg = 'Please Select a items';
            }
            $message = $msg;
            set_message($type, $message);
            if ($is_ajax) {
                $this->estimate_json_response($type, $message, $type === 'success' ? $redirect_url : null);
            }
            redirect($redirect_url);
        } else {
            set_message('error', lang('there_in_no_value'));
            if ($is_ajax) {
                $this->estimate_json_response('error', lang('there_in_no_value'));
            }
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }
    }

    function update_invoice_tax($saved_items_id, $estimates_id)
    {
        $estimate_items = $this->db->where('estimates_id', $estimates_id)->get('tbl_estimate_items')->result();
        $results = array();
        if (!empty($estimate_items)) {
            foreach ($estimate_items as $item) {
                $item_tax_names = !empty($item->item_tax_name) ? json_decode($item->item_tax_name, true) : array();
                if (empty($item_tax_names) || !is_array($item_tax_names)) {
                    continue;
                }
                foreach ($item_tax_names as $tax_name) {
                    if (empty($tax_name) || strpos($tax_name, '|') === false) {
                        continue;
                    }
                    $parts = explode('|', $tax_name);
                    $tax_label = $parts[0] . '|' . (isset($parts[1]) ? $parts[1] : 0);
                    $tax_amount = ((float) $item->unit_cost * (float) $item->quantity / 100) * (float) (isset($parts[1]) ? $parts[1] : 0);
                    if (!isset($results[$tax_label])) {
                        $results[$tax_label] = 0;
                    }
                    $results[$tax_label] += $tax_amount;
                }
            }
        }

        $invoice_data = array('tax' => 0, 'total_tax' => '');
        if (!empty($results)) {
            $structured_results = array('tax_name' => array(), 'total_tax' => array());
            foreach ($results as $key => $value) {
                $structured_results['tax_name'][] = $key;
                $structured_results['total_tax'][] = $value;
            }
            $invoice_data['tax'] = array_sum($structured_results['total_tax']);
            $invoice_data['total_tax'] = json_encode($structured_results);
        }

        $this->estimates_model->_table_name = 'tbl_estimates';
        $this->estimates_model->_primary_key = 'estimates_id';
        $this->estimates_model->save($invoice_data, $estimates_id);
        return true;
    }

    public
    function add_item($id = NULL)
    {
        $data = $this->estimates_model->array_from_post(array('estimates_id', 'item_order'));
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $data['estimates_id']));
        $edited = can_action('14', 'edited');
        if (!empty($can_edit) && !empty($edited)) {
            $quantity = $this->input->post('quantity', TRUE);
            $array_data = $this->estimates_model->array_from_post(array('item_name', 'item_desc', 'item_tax_rate', 'unit_cost'));
            if (!empty($quantity)) {
                foreach ($quantity as $key => $value) {
                    $data['quantity'] = $value;
                    $data['item_name'] = $array_data['item_name'][$key];
                    $data['item_desc'] = $array_data['item_desc'][$key];
                    $data['unit_cost'] = $array_data['unit_cost'][$key];
                    $data['item_tax_rate'] = $array_data['item_tax_rate'][$key];
                    $sub_total = $data['unit_cost'] * $data['quantity'];

                    $data['item_tax_total'] = ($data['item_tax_rate'] / 100) * $sub_total;
                    $data['total_cost'] = $sub_total + $data['item_tax_total'];

                    // get all client
                    $this->estimates_model->_table_name = 'tbl_estimate_items';
                    $this->estimates_model->_primary_key = 'estimate_items_id';
                    if (!empty($id)) {
                        $estimate_items_id = $id;
                        $this->estimates_model->save($data, $id);
                        $action = ('activity_estimates_items_updated');
                    } else {
                        $estimate_items_id = $this->estimates_model->save($data);
                        $action = 'activity_estimates_items_added';
                    }
                    $activity = array(
                        'user' => $this->session->userdata('user_id'),
                        'module' => 'estimates',
                        'module_field_id' => $estimate_items_id,
                        'activity' => $action,
                        'icon' => 'fa-shopping-cart',
                        'link' => 'admin/estimates/create/estimates_details/' . $data['estimates_id'],
                        'value1' => $data['item_name']
                    );
                    $this->estimates_model->_table_name = 'tbl_activities';
                    $this->estimates_model->_primary_key = 'activities_id';
                    $this->estimates_model->save($activity);
                }
            }
            // messages for user
            $type = "success";
            $message = lang('estimate_item_save');
            set_message($type, $message);
            redirect('admin/estimates/create/estimates_details/' . $data['estimates_id']);
        } else {
            set_message('error', lang('there_in_no_value'));
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }
    }

    public
    function clone_estimate($estimates_id)
    {
        $edited = can_action('14', 'edited');
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $estimates_id));
        if (!empty($can_edit) && !empty($edited) && !empty($estimates_id)) {
            $data['estimate_info'] = $this->estimates_model->check_by(array('estimates_id' => $estimates_id), 'tbl_estimates');
            if (empty($data['estimate_info'])) {
                show_404();
            }
            // get all client
            $this->estimates_model->_table_name = 'tbl_client';
            $this->estimates_model->_order_by = 'client_id';
            $data['all_client'] = $this->estimates_model->get();

            $data['modal_subview'] = $this->load->view('admin/estimates/_modal_clone_estimate', $data, TRUE);
            $this->output->set_output($data['modal_subview']);
        } else {
            set_message('error', lang('there_in_no_value'));
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }
    }

    public
    function cloned_estimate($id)
    {
        $edited = can_action('14', 'edited');
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
        if (!empty($can_edit) && !empty($edited)) {
            if (config_item('increment_estimate_number') == 'FALSE') {
                $this->load->helper('string');
                $reference_no = config_item('estimate_prefix') . ' ' . random_string('nozero', 6);
            } else {
                $reference_no = config_item('estimate_prefix') . ' ' . $this->estimates_model->generate_estimate_number();
            }

            $invoice_info = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');
            $data['estimate_date'] = date('Y-m-d', safe_strtotime($this->input->post('estimate_date', TRUE)));
            if (empty($data['estimate_date'])) {
                $data['estimate_date'] = date('Y-m-d');
            }
            // save into invoice table
            $new_invoice = array(
                'reference_no' => $reference_no,
                'client_id' => $this->input->post('client_id', true),
                'project_id' => $invoice_info->project_id,
                'estimate_date' => date('Y-m-d', safe_strtotime($this->input->post('estimate_date', TRUE))),
                'estimate_month' => date('Y-m', safe_strtotime($this->input->post('estimate_date', TRUE))),
                'estimate_year' => date('Y', safe_strtotime($this->input->post('estimate_date', TRUE))),
                'due_date' => date('Y-m-d', safe_strtotime($this->input->post('due_date', TRUE))),
                'notes' => $invoice_info->notes,
                'tags' => $invoice_info->tags,
                'total_tax' => $invoice_info->total_tax,
                'tax' => $invoice_info->tax,
                'discount_type' => $invoice_info->discount_type,
                'discount_percent' => $invoice_info->discount_percent,
                'user_id' => $invoice_info->user_id,
                'adjustment' => $invoice_info->adjustment,
                'discount_total' => $invoice_info->discount_total,
                'show_quantity_as' => $invoice_info->show_quantity_as,
                'currency' => $invoice_info->currency,
                'status' => $invoice_info->status,
                'date_sent' => $invoice_info->date_sent,
                'date_saved' => $invoice_info->date_saved,
                'emailed' => $invoice_info->emailed,
                'show_client' => $invoice_info->show_client,
                'invoiced' => $invoice_info->invoiced,
                'invoices_id' => $invoice_info->invoices_id,
                'permission' => $invoice_info->permission,
            );
            $this->estimates_model->_table_name = "tbl_estimates"; //table name
            $this->estimates_model->_primary_key = "estimates_id";
            $new_invoice_id = $this->estimates_model->save($new_invoice);

            $invoice_items = $this->db->where('estimates_id', $id)->get('tbl_estimate_items')->result();

            if (!empty($invoice_items)) {
                foreach ($invoice_items as $new_item) {
                    $items = array(
                        'estimates_id' => $new_invoice_id,
                        'item_name' => $new_item->item_name,
                        'item_desc' => $new_item->item_desc,
                        'unit_cost' => $new_item->unit_cost,
                        'quantity' => $new_item->quantity,
                        'item_tax_rate' => $new_item->item_tax_rate,
                        'item_tax_name' => $new_item->item_tax_name,
                        'item_tax_total' => $new_item->item_tax_total,
                        'total_cost' => $new_item->total_cost,
                        'unit' => $new_item->unit,
                        'order' => $new_item->order,
                        'date_saved' => $new_item->date_saved,
                    );
                    $this->estimates_model->_table_name = "tbl_estimate_items"; //table name
                    $this->estimates_model->_primary_key = "estimate_items_id";
                    $this->estimates_model->save($items);
                }
            }
            // save into activities
            $activities = array(
                'user' => $this->session->userdata('user_id'),
                'module' => 'estimates',
                'module_field_id' => $new_invoice_id,
                'activity' => ('activity_clone_estimate'),
                'icon' => 'fa-shopping-cart',
                'link' => 'admin/estimates/create/estimates_details/' . $new_invoice_id,
                'value1' => ' from ' . $invoice_info->reference_no . ' to ' . $reference_no,
            );
            // Update into tbl_project
            $this->estimates_model->_table_name = "tbl_activities"; //table name
            $this->estimates_model->_primary_key = "activities_id";
            $this->estimates_model->save($activities);

            // messages for user
            $type = "success";
            $message = lang('estimate_created');
            set_message($type, $message);
            if ($this->input->is_ajax_request()) {
                echo json_encode(array(
                    'status' => $type,
                    'message' => $message,
                    'url' => 'admin/estimates/estimates_details/' . $new_invoice_id,
                ));
                exit();
            }
            redirect('admin/estimates/estimates_details/' . $new_invoice_id);

        } else {
            if ($this->input->is_ajax_request()) {
                echo json_encode(array('status' => 'error', 'message' => lang('there_in_no_value')));
                exit();
            }
            redirect('admin/estimates');
        }
    }

    public
    function change_status($action, $id)
    {
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
        $edited = can_action('14', 'edited');
        if (!empty($can_edit) && !empty($edited)) {
            $where = array('estimates_id' => $id);
            if ($action == 'hide') {
                $data = array('show_client' => 'No');
            } elseif ($action == 'show') {
                $data = array('show_client' => 'Yes');
            } elseif ($action == 'sent') {
                $data = array('emailed' => 'Yes', 'date_sent' => date("Y-m-d H:i:s", time()), 'status' => 'sent');
            } elseif (!empty($action)) {
                $data = array('status' => $action);
            } else {
                $data = array('show_client' => 'Yes');
            }
            $this->estimates_model->set_action($where, $data, 'tbl_estimates');
            // messages for user
            $type = "success";
            $message = lang('estimate_status_changed', $action);
            set_message($type, $message);
            redirect('admin/estimates/create/estimates_details/' . $id);
        } else {
            set_message('error', lang('there_in_no_value'));
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }
    }

    public
    function delete($action, $estimates_id, $item_id = NULL)
    {
        $can_delete = $this->estimates_model->can_action('tbl_estimates', 'delete', array('estimates_id' => $estimates_id));
        $deleted = can_action('14', 'deleted');
        if (!empty($can_delete) && !empty($deleted)) {
            if ($action == 'delete_item') {
                $this->estimates_model->_table_name = 'tbl_estimate_items';
                $this->estimates_model->_primary_key = 'estimate_items_id';
                $this->estimates_model->delete($item_id);
            } elseif ($action == 'delete_estimates') {

                $this->estimates_model->_table_name = 'tbl_estimate_items';
                $this->estimates_model->delete_multiple(array('estimates_id' => $estimates_id));

                $this->estimates_model->_table_name = 'tbl_reminders';
                $this->estimates_model->delete_multiple(array('module' => 'estimate', 'module_id' => $estimates_id));

                $this->estimates_model->_table_name = 'tbl_pinaction';
                $this->estimates_model->delete_multiple(array('module_name' => 'estimates', 'module_id' => $estimates_id));

                $this->estimates_model->_table_name = 'tbl_estimates';
                $this->estimates_model->_primary_key = 'estimates_id';
                $this->estimates_model->delete($estimates_id);
            }
            $activity = array(
                'user' => $this->session->userdata('user_id'),
                'module' => 'estimates',
                'module_field_id' => $estimates_id,
                'activity' => ('activity_' . $action),
                'icon' => 'fa-shopping-cart',
                'value1' => $action
            );

            $this->estimates_model->_table_name = 'tbl_activities';
            $this->estimates_model->_primary_key = 'activities_id';
            $this->estimates_model->save($activity);
            $type = 'success';
            if ($action == 'delete_item') {
                $text = lang('estimate_item_deleted');
                //                set_message($type, $text);
                //                redirect('admin/estimates/create/estimates_details/' . $estimates_id);
            } else {
                $text = lang('estimate_deleted');

                //                set_message($type, $text);
                //                redirect('admin/estimates');
            }
            echo json_encode(array("status" => $type, 'message' => $text));
            exit();
        } else {
            echo json_encode(array("status" => 'error', 'message' => lang('there_in_no_value')));
            exit();
            //            set_message('error', lang('there_in_no_value'));
            //            redirect($_SERVER['HTTP_REFERER']);
        }
    }

    public
    function send_estimates_email($estimates_id, $row = null)
    {
        if (!empty($row)) {
            $estimates_info = $this->estimates_model->check_by(array('estimates_id' => $estimates_id), 'tbl_estimates');
            $client_info = $this->estimates_model->check_by(array('client_id' => $estimates_info->client_id), 'tbl_client');
            if (!empty($client_info)) {
                $client = $client_info->name;
                $currency = $this->estimates_model->client_currency_symbol($client_info->client_id);;
            } else {
                $client = '-';
                $currency = $this->estimates_model->check_by(array('code' => config_item('default_currency')), 'tbl_currencies');
            }

            $amount = $this->estimates_model->estimate_calculation('total', $estimates_info->estimates_id);
            $currency = $currency->code;
            $email_template = email_templates(array('email_group' => 'estimate_email'), $estimates_info->client_id);
            $message = $email_template->template_body;
            $ref = $estimates_info->reference_no;
            $subject = $email_template->subject;
        } else {
            $message = $this->input->post('message', TRUE);
            $ref = $this->input->post('ref', TRUE);
            $subject = $this->input->post('subject', TRUE);
            $client = $this->input->post('client_name', TRUE);
            $amount = $this->input->post('amount', true);
            $currency = $this->input->post('currency', TRUE);
        }
        $client_name = str_replace("{CLIENT}", $client, $message);
        $Ref = str_replace("{ESTIMATE_REF}", $ref, $client_name);
        $Amount = str_replace("{AMOUNT}", $amount, $Ref);
        $Currency = str_replace("{CURRENCY}", $currency, $Amount);


        $link = str_replace("{ESTIMATE_LINK}", base_url() . 'frontend/estimates/' . url_encode($estimates_id), $Currency);
        $message = str_replace("{SITE_NAME}", config_item('company_name'), $link);


        $this->send_email_estimates($estimates_id, $message, $subject); // Email estimates

        $data = array('status' => 'sent', 'emailed' => 'Yes', 'date_sent' => date("Y-m-d H:i:s", time()));

        $this->estimates_model->_table_name = 'tbl_estimates';
        $this->estimates_model->_primary_key = 'estimates_id';
        $this->estimates_model->save($data, $estimates_id);

        // Log Activity
        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'estimates',
            'module_field_id' => $estimates_id,
            'activity' => 'activity_estimates_sent',
            'icon' => 'fa-shopping-cart',
            'link' => 'admin/estimates/create/estimates_details/' . $estimates_id,
            'value1' => $ref
        );
        $this->estimates_model->_table_name = 'tbl_activities';
        $this->estimates_model->_primary_key = 'activities_id';
        $this->estimates_model->save($activity);

        $type = 'success';
        $text = lang('estimate_email_sent');
        set_message($type, $text);
        redirect('admin/estimates/create/estimates_details/' . $estimates_id);
    }

    function send_email_estimates($estimates_id, $message, $subject)
    {
        $estimates_info = $this->estimates_model->check_by(array('estimates_id' => $estimates_id), 'tbl_estimates');
        $client_info = $this->estimates_model->check_by(array('client_id' => $estimates_info->client_id), 'tbl_client');

        $recipient = $client_info->email;

        $data['message'] = $message;

        $message = $this->load->view('email_template', $data, TRUE);
        $params = array(
            'recipient' => $recipient,
            'subject' => $subject,
            'message' => $message
        );
        $params['resourceed_file'] = 'uploads/' . slug_it(lang('estimates') . '_pdf_' . $estimates_info->reference_no) . '.pdf';
        $params['resourcement_url'] = base_url() . 'uploads/' . slug_it(lang('estimates') . '_pdf_' . $estimates_info->reference_no) . '.pdf';

        $this->attach_pdf($estimates_id);

        $this->estimates_model->send_email($params);
        //Delete estimate in tmp folder
        if (is_file('uploads/' . slug_it(lang('estimates') . '_pdf_' . $estimates_info->reference_no) . '.pdf')) {
            unlink('uploads/' . slug_it(lang('estimates') . '_pdf_' . $estimates_info->reference_no) . '.pdf');
        }
        // send notification to client
        if (!empty($client_info->primary_contact)) {
            $notifyUser = array($client_info->primary_contact);
        } else {
            $user_info = $this->estimates_model->check_by(array('company' => $estimates_info->client_id), 'tbl_account_details');
            if (!empty($user_info)) {
                $notifyUser = array($user_info->user_id);
            }
        }
        if (!empty($notifyUser)) {
            foreach ($notifyUser as $v_user) {
                if ($v_user != $this->session->userdata('user_id')) {
                    add_notification(array(
                        'to_user_id' => $v_user,
                        'icon' => 'shopping-cart',
                        'description' => 'not_email_send_alert',
                        'link' => 'client/estimates/index/estimates_details/' . $estimates_id,
                        'value' => lang('estimate') . ' ' . $estimates_info->reference_no,
                    ));
                }
            }
            show_notification($notifyUser);
        }
    }

    public
    function attach_pdf($id)
    {
        $this->estimates_details($id, 'attach');
    }

    function estimate_email($estimates_id)
    {
        $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $estimates_id), 'tbl_estimates');
        $estimates_info = $data['estimates_info'];
        $client_info = $this->estimates_model->check_by(array('client_id' => $data['estimates_info']->client_id), 'tbl_client');

        $recipient = $client_info->email;

        $message = $this->load->view('admin/estimates/estimates_pdf', $data, TRUE);

        $data['message'] = $message;

        $message = $this->load->view('email_template', $data, TRUE);
        $params = array(
            'recipient' => $recipient,
            'subject' => '[ ' . config_item('company_name') . ' ]' . ' New Estimate' . ' ' . $data['estimates_info']->reference_no,
            'message' => $message
        );
        $params['resourceed_file'] = '';

        $this->estimates_model->send_email($params);

        $data = array('emailed' => 'Yes', 'date_sent' => date("Y-m-d H:i:s", time()));

        $this->estimates_model->_table_name = 'tbl_estimates';
        $this->estimates_model->_primary_key = 'estimates_id';
        $this->estimates_model->save($data, $estimates_id);

        // Log Activity
        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'estimates',
            'module_field_id' => $estimates_id,
            'activity' => 'activity_estimates_sent',
            'icon' => 'fa-shopping-cart',
            'link' => 'admin/estimates/create/estimates_details/' . $estimates_id,
            'value1' => $estimates_info->reference_no
        );
        $this->estimates_model->_table_name = 'tbl_activities';
        $this->estimates_model->_primary_key = 'activities_id';
        $this->estimates_model->save($activity);

        // send notification to client
        if (!empty($client_info->primary_contact)) {
            $notifyUser = array($client_info->primary_contact);
        } else {
            $user_info = $this->estimates_model->check_by(array('company' => $estimates_info->client_id), 'tbl_account_details');
            if (!empty($user_info)) {
                $notifyUser = array($user_info->user_id);
            }
        }
        if (!empty($notifyUser)) {
            foreach ($notifyUser as $v_user) {
                if ($v_user != $this->session->userdata('user_id')) {
                    add_notification(array(
                        'to_user_id' => $v_user,
                        'icon' => 'shopping-cart',
                        'description' => 'not_email_send_alert',
                        'link' => 'client/estimates/index/estimates_details/' . $estimates_id,
                        'value' => lang('estimate') . ' ' . $estimates_info->reference_no,
                    ));
                }
            }
            show_notification($notifyUser);
        }


        $type = 'success';
        $text = lang('estimate_email_sent');
        set_message($type, $text);
        redirect('admin/estimates/create/estimates_details/' . $estimates_id);
    }

    public
    function convert_to_invoice($id)
    {
        $data['title'] = lang('convert_to_invoice');
        $edited = can_action('14', 'edited');
        $can_edit = $this->estimates_model->can_action('tbl_estimates', 'edit', array('estimates_id' => $id));
        if (!empty($can_edit) && !empty($edited)) {
            // get all client
            $this->estimates_model->_table_name = 'tbl_client';
            $this->estimates_model->_order_by = 'client_id';
            $data['all_client'] = $this->estimates_model->get();
            // get permission user
            $data['permission_user'] = $this->estimates_model->all_permission_user('14');

            $data['estimates_info'] = $this->estimates_model->check_by(array('estimates_id' => $id), 'tbl_estimates');

            $data['modal_subview'] = $this->load->view('admin/estimates/convert_to_invoice', $data, FALSE);
        } else {
            set_message('error', lang('there_in_no_value'));
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }
    }

    public
    function converted($estimate_id)
    {
        $data = $this->estimates_model->array_from_post(array('reference_no', 'client_id', 'project_id', 'warehouse_id', 'discount_type', 'discount_percent', 'user_id', 'adjustment', 'discount_total', 'show_quantity_as'));
        if (empty($data['warehouse_id'])) {
            $estimate_info = $this->estimates_model->check_by(array('estimates_id' => $estimate_id), 'tbl_estimates');
            if (!empty($estimate_info->warehouse_id)) {
                $data['warehouse_id'] = $estimate_info->warehouse_id;
            } else {
                $data['warehouse_id'] = $this->session->userdata('warehouse_id');
            }
        }
        $this->db->trans_begin();
        $stock_ok = true;
        $stock_error = lang('stock_update_failed');

        $all_payment = get_result('tbl_online_payment');
        foreach ($all_payment as $payment) {
            $allow_gateway = 'allow_' . slug_it(strtolower($payment->gateway_name));
            $gateway_status = slug_it(strtolower($payment->gateway_name)) . '_status';
            if (config_item($gateway_status) == 'active') {
                $data[$allow_gateway] = ($this->input->post($allow_gateway) == 'Yes') ? 'Yes' : 'No';
            }
        }

        $data['client_visible'] = ($this->input->post('client_visible') == 'Yes') ? 'Yes' : 'No';
        $data['invoice_date'] = date('Y-m-d', safe_strtotime($this->input->post('invoice_date', TRUE)));
        if (empty($data['invoice_date'])) {
            $data['invoice_date'] = date('Y-m-d');
        }
        $data['invoice_year'] = date('Y', safe_strtotime($this->input->post('invoice_date', TRUE)));
        $data['invoice_month'] = date('Y-m', safe_strtotime($this->input->post('invoice_date', TRUE)));
        $data['due_date'] = date('Y-m-d', safe_strtotime($this->input->post('due_date', TRUE)));
        $data['notes'] = $this->input->post('notes', TRUE);
        $tax['tax_name'] = $this->input->post('total_tax_name', TRUE);
        $tax['total_tax'] = $this->input->post('total_tax', TRUE);
        $data['total_tax'] = json_encode($tax);
        $i_tax = 0;
        if (!empty($tax['total_tax'])) {
            foreach ($tax['total_tax'] as $v_tax) {
                $i_tax += $v_tax;
            }
        }
        $data['tax'] = $i_tax;
        $save_as_draft = $this->input->post('save_as_draft', TRUE);
        if (!empty($save_as_draft)) {
            $data['status'] = 'draft';
        }
        $currency = $this->estimates_model->client_currency_symbol($data['client_id']);
        if (!empty($currency->code)) {
            $curren = $currency->code;
        } else {
            $curren = config_item('default_currency');
        }
        $data['currency'] = $curren;

        $permission = $this->input->post('permission', true);
        if (!empty($permission)) {
            if ($permission == 'everyone') {
                $assigned = 'all';
            } else {
                $assigned_to = $this->estimates_model->array_from_post(array('assigned_to'));
                if (!empty($assigned_to['assigned_to'])) {
                    foreach ($assigned_to['assigned_to'] as $assign_user) {
                        $assigned[$assign_user] = $this->input->post('action_' . $assign_user, true);
                    }
                }
            }
            if (!empty($assigned)) {
                if ($assigned != 'all') {
                    $assigned = json_encode($assigned);
                }
            } else {
                $assigned = 'all';
            }
            $data['permission'] = $assigned;
        } else {
            $this->db->trans_rollback();
            set_message('error', lang('assigned_to') . ' Field is required');
            if ($this->input->is_ajax_request()) {
                echo json_encode(array('status' => 'error', 'message' => lang('assigned_to') . ' Field is required'));
                exit();
            }
            if (empty($_SERVER['HTTP_REFERER'])) {
                redirect('admin/estimates');
            } else {
                redirect($_SERVER['HTTP_REFERER']);
            }
        }

        // get all client
        $this->estimates_model->_table_name = 'tbl_invoices';
        $this->estimates_model->_primary_key = 'invoices_id';

        $invoice_id = $this->estimates_model->save($data);
        $recuring_frequency = $this->input->post('recuring_frequency', TRUE);

        if (!empty($recuring_frequency) && $recuring_frequency != 'none') {
            $recur_data = $this->estimates_model->array_from_post(array('recur_start_date', 'recur_end_date'));
            $recur_data['recuring_frequency'] = $recuring_frequency;
            $this->get_recuring_frequency($invoice_id, $recur_data); // set recurring
        }
        // save items
        $qty_calculation = config_item('qty_calculation_from_items');
        // save items
        $invoices_to_merge = $this->input->post('invoices_to_merge', TRUE);
        $cancel_merged_invoices = $this->input->post('cancel_merged_invoices', TRUE);
        if (!empty($invoices_to_merge)) {
            foreach ($invoices_to_merge as $inv_id) {
                if (empty($cancel_merged_invoices)) {
                    if (!empty($qty_calculation) && $qty_calculation == 'Yes') {
                        $all_items_info = $this->db->where('invoices_id', $inv_id)->get('tbl_items')->result();
                        if (!empty($all_items_info)) {
                            foreach ($all_items_info as $v_items) {
                                if (!$this->estimates_model->return_items($v_items->saved_items_id, $v_items->quantity, $data['warehouse_id'])) {
                                    $stock_ok = false;
                                    break;
                                }
                            }
                        }
                        if (!$stock_ok) {
                            break;
                        }
                    }
                    $this->db->where('invoices_id', $inv_id);
                    $this->db->delete('tbl_invoices');

                    $this->db->where('invoices_id', $inv_id);
                    $this->db->delete('tbl_items');
                } else {
                    $mdata = array('status' => 'Cancelled');
                    $this->estimates_model->_table_name = 'tbl_invoices';
                    $this->estimates_model->_primary_key = 'invoices_id';
                    $this->estimates_model->save($mdata, $inv_id);
                }
            }
            if (!$stock_ok) {
                $this->db->trans_rollback();
                set_message('error', $stock_error);
                if ($this->input->is_ajax_request()) {
                    echo json_encode(array('status' => 'error', 'message' => $stock_error));
                    exit();
                }
                redirect($_SERVER['HTTP_REFERER']);
            }
        }

        $removed_items = $this->input->post('removed_items', TRUE);
        if (!empty($removed_items)) {
            foreach ($removed_items as $r_id) {
                if ($r_id != 'undefined') {
                    if (!empty($qty_calculation) && $qty_calculation == 'Yes') {
                        $itemInfo = get_row('tbl_items', array('items_id' => $r_id));
                        if (!$this->estimates_model->return_items($itemInfo->saved_items_id, $itemInfo->quantity, $data['warehouse_id'])) {
                            $stock_ok = false;
                            break;
                        }
                    }
                    $this->db->where('items_id', $r_id);
                    $this->db->delete('tbl_items');
                }
            }
        }
        if (!$stock_ok) {
            $this->db->trans_rollback();
            set_message('error', $stock_error);
            if ($this->input->is_ajax_request()) {
                echo json_encode(array('status' => 'error', 'message' => $stock_error));
                exit();
            }
            redirect($_SERVER['HTTP_REFERER']);
        }

        $itemsid = $this->input->post('items_id', TRUE);
        $items_data = $this->input->post('items', true);
        if (!empty($items_data)) {
            $index = 0;
            foreach ($items_data as $items) {
                $items['invoices_id'] = $invoice_id;
                $tax = 0;
                if (!empty($items['taxname'])) {
                    foreach ($items['taxname'] as $tax_name) {
                        $tax_rate = explode("|", $tax_name);
                        $tax += $tax_rate[1];
                    }
                    $items['item_tax_name'] = $items['taxname'];
                    unset($items['taxname']);
                    $items['item_tax_name'] = json_encode($items['item_tax_name']);
                }
                if (empty($items['saved_items_id'])) {
                    $items['saved_items_id'] = 0;
                }
                $price = $items['quantity'] * $items['unit_cost'];
                $items['item_tax_total'] = ($price / 100 * $tax);
                $items['total_cost'] = $price;
                // get all client
                $this->estimates_model->_table_name = 'tbl_items';
                $this->estimates_model->_primary_key = 'items_id';
                if (!empty($qty_calculation) && $qty_calculation == 'Yes') {
                    if (!empty($items['saved_items_id']) && $items['saved_items_id'] != 'undefined') {
                        if (empty($data['warehouse_id']) && config_item('require_warehouse_for_stock')) {
                            $stock_ok = false;
                            $stock_error = 'Please select a warehouse before converting this estimate.';
                            break;
                        }
                        $this->ensure_estimate_conversion_warehouse_stock($items['saved_items_id'], $data['warehouse_id']);
                        if (!$this->estimates_model->reduce_items($items['saved_items_id'], $items['quantity'], $data['warehouse_id'])) {
                            $stock_ok = false;
                            break;
                        }
                    }
                }
                $items_id = $this->estimates_model->save($items);
                $index++;
            }
        }
        if (!$stock_ok || $this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            set_message('error', $stock_error);
            if ($this->input->is_ajax_request()) {
                echo json_encode(array('status' => 'error', 'message' => $stock_error));
                exit();
            }
            redirect($_SERVER['HTTP_REFERER']);
        }

        $e_data = array('status' => 'accepted', 'invoiced' => 'Yes', 'invoices_id' => $invoice_id);

        $this->estimates_model->_table_name = 'tbl_estimates';
        $this->estimates_model->_primary_key = 'estimates_id';
        $this->estimates_model->save($e_data, $estimate_id);

        $activity = array(
            'user' => $this->session->userdata('user_id'),
            'module' => 'estimates',
            'module_field_id' => $estimate_id,
            'activity' => 'activity_estimate_convert_to_invoice',
            'icon' => 'fa-shopping-cart',
            'link' => 'admin/estimates/create/estimates_details/' . $estimate_id,
            'value1' => $data['reference_no']
        );
        $this->estimates_model->_table_name = 'tbl_activities';
        $this->estimates_model->_primary_key = 'activities_id';
        $this->estimates_model->save($activity);
        $this->db->trans_commit();

        // send notification to client
        if (!empty($data['client_id'])) {
            $client_info = $this->estimates_model->check_by(array('client_id' => $data['client_id']), 'tbl_client');
            if (!empty($client_info->primary_contact)) {
                $notifyUser = array($client_info->primary_contact);
            } else {
                $user_info = $this->estimates_model->check_by(array('company' => $data['client_id']), 'tbl_account_details');
                if (!empty($user_info)) {
                    $notifyUser = array($user_info->user_id);
                }
            }
        }
        if (!empty($notifyUser)) {
            foreach ($notifyUser as $v_user) {
                if ($v_user != $this->session->userdata('user_id')) {
                    add_notification(array(
                        'to_user_id' => $v_user,
                        'icon' => 'shopping-cart',
                        'description' => 'proposal_convert_to_invoice',
                        'link' => 'client/invoice/manage_invoice/invoice_details/' . $invoice_id,
                        'value' => $data['reference_no'],
                    ));
                }
            }
            show_notification($notifyUser);
        }
        // messages for user
        $type = "success";
        $message = lang('estimate_invoiced');
        set_message($type, $message);
        if ($this->input->is_ajax_request()) {
            echo json_encode(array(
                'status' => $type,
                'message' => $message,
                'url' => 'admin/estimates/create/estimates_details/' . $estimate_id,
            ));
            exit();
        }
        redirect('admin/estimates/create/estimates_details/' . $estimate_id);
    }

    function check_existing_qty($items_id, $qty, $warehouseId)
    {
        $items_info = $this->db->where('items_id', $items_id)->get('tbl_items')->row();
        if (!empty($items_info)) {
            if ($items_info->quantity != $qty) {
                if ($qty > $items_info->quantity) {
                    $reduce_qty = $qty - $items_info->quantity;
                    if (!empty($items_info->saved_items_id)) {
                        $this->ensure_estimate_conversion_warehouse_stock($items_info->saved_items_id, $warehouseId);
                        if (!$this->estimates_model->reduce_items($items_info->saved_items_id, $reduce_qty, $warehouseId)) {
                            return false;
                        }
                    }
                }
                if ($qty < $items_info->quantity) {
                    $return_qty = $items_info->quantity - $qty;
                    if (!empty($items_info->saved_items_id)) {
                        if (!$this->estimates_model->return_items($items_info->saved_items_id, $return_qty, $warehouseId)) {
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }

    function get_recuring_frequency($invoices_id, $recur_data)
    {
        $recur_days = $this->get_calculate_recurring_days($recur_data['recuring_frequency']);
        $due_date = $this->estimates_model->get_table_field('tbl_invoices', array('invoices_id' => $invoices_id), 'due_date');

        $next_date = date("Y-m-d", safe_strtotime($due_date . "+ " . $recur_days . " days"));

        if ($recur_data['recur_end_date'] == '') {
            $recur_end_date = '0000-00-00';
        } else {
            $recur_end_date = date('Y-m-d', safe_strtotime($recur_data['recur_end_date']));
        }
        $update_invoice = array(
            'recurring' => 'Yes',
            'recuring_frequency' => $recur_days,
            'recur_frequency' => $recur_data['recuring_frequency'],
            'recur_start_date' => date('Y-m-d', safe_strtotime($recur_data['recur_start_date'])),
            'recur_end_date' => $recur_end_date,
            'recur_next_date' => $next_date
        );
        $this->estimates_model->_table_name = 'tbl_invoices';
        $this->estimates_model->_primary_key = 'invoices_id';
        $this->estimates_model->save($update_invoice, $invoices_id);
        return TRUE;
    }

    function get_calculate_recurring_days($recuring_frequency)
    {
        switch ($recuring_frequency) {
            case '7D':
                return 7;
                break;
            case '1M':
                return 31;
                break;
            case '3M':
                return 90;
                break;
            case '6M':
                return 182;
                break;
            case '1Y':
                return 365;
                break;
        }
    }
}
