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

class Auth extends MY_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->lang->load('auth', $this->Settings->language);
        $this->load->library('form_validation');
        $this->form_validation->set_error_delimiters($this->config->item('error_start_delimiter', 'ion_auth'), $this->config->item('error_end_delimiter', 'ion_auth'));
        $this->load->model('auth_model');
        $this->load->library('ion_auth');
    }

    public function _get_csrf_nonce()
    {
        $this->load->helper('string');
        $key   = random_string('alnum', 8);
        $value = random_string('alnum', 20);
        $this->session->set_flashdata('csrfkey', $key);
        $this->session->set_flashdata('csrfvalue', $value);

        return [$key => $value];
    }

    public function _render_page($view, $data = null, $render = false)
    {
        $this->viewdata = (empty($data)) ? $this->data : $data;
        $view_html      = $this->load->view('header', $this->viewdata, $render);
        $view_html .= $this->load->view($view, $this->viewdata, $render);
        $view_html = $this->load->view('footer', $this->viewdata, $render);

        if (!$render) {
            return $view_html;
        }
    }

    public function _valid_csrf_nonce()
    {
        if ($this->input->post($this->session->flashdata('csrfkey')) !== false && $this->input->post($this->session->flashdata('csrfkey')) == $this->session->flashdata('csrfvalue')) {
            return true;
        }
        return false;
    }

    public function activate($id, $code = false)
    {
        if ($code !== false) {
            $activation = $this->ion_auth->activate($id, $code);
        } elseif ($this->Admin) {
            $activation = $this->ion_auth->activate($id);
        }

        if ($activation) {
            $this->session->set_flashdata('message', $this->ion_auth->messages());
            if ($this->Admin) {
                redirect($_SERVER['HTTP_REFERER']);
            } else {
                redirect('auth/login');
            }
        } else {
            $this->session->set_flashdata('error', $this->ion_auth->errors());
            redirect('forgot_password');
        }
    }

    public function captcha_check($cap)
    {
        $expiration = time() - 300;
        $this->db->query('DELETE FROM captcha WHERE captcha_time < ' . $expiration);

        $sql   = 'SELECT COUNT(*) AS count FROM captcha WHERE word = ? AND ip_address = ? AND captcha_time > ?';
        $binds = [$cap, $this->input->ip_address(), $expiration];
        $query = $this->db->query($sql, $binds);
        $row   = $query->row();
        if ($row->count == 0) {
            $this->form_validation->set_message('captcha_check', lang('captcha_wrong'));
            return false;
        }
        return true;
    }

    public function change_password()
    {
        if (!$this->ion_auth->logged_in()) {
            redirect('login');
        }
        $this->form_validation->set_rules('old_password', lang('old_password'), 'required');
        $this->form_validation->set_rules('new_password', lang('new_password'), 'required|max_length[25]');
        $this->form_validation->set_rules('new_password_confirm', lang('confirm_password'), 'required|matches[new_password]');

        $user = $this->ion_auth->user()->row();

        if ($this->form_validation->run() == false) {
            $this->session->set_flashdata('error', validation_errors());
            redirect('auth/profile/' . $user->id . '/#cpassword');
        } else {
            if (DEMO) {
                $this->session->set_flashdata('error', lang('disabled_in_demo'));
                redirect($_SERVER['HTTP_REFERER'] ?? 'welcome');
            }

            $identity = $this->session->userdata($this->config->item('identity', 'ion_auth'));

            $change = $this->ion_auth->change_password($identity, $this->input->post('old_password'), $this->input->post('new_password'));

            if ($change) {
                $this->session->set_flashdata('message', $this->ion_auth->messages());
                $this->logout();
            } else {
                $this->session->set_flashdata('error', $this->ion_auth->errors());
                redirect('auth/profile/' . $user->id . '/#cpassword');
            }
        }
    }

    public function create_user()
    {
        if (!$this->Admin) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }

        $this->data['title'] = lang('add_user');
        $this->form_validation->set_rules('username', lang('username'), 'trim|is_unique[users.username]');
        $this->form_validation->set_rules('email', lang('email'), 'trim|is_unique[users.email]');

        if ($this->form_validation->run() == true) {
            $username = strtolower($this->input->post('username'));
            $email    = strtolower($this->input->post('email'));
            $password = $this->input->post('password');
            $notify   = $this->input->post('notify');

            $additional_data = [
                'first_name' => $this->input->post('first_name'),
                'last_name'  => $this->input->post('last_name'),
                'phone'      => $this->input->post('phone'),
                'gender'     => $this->input->post('gender'),
                'store_id'   => $this->input->post('group') == 1 ? null : $this->input->post('store_id'),
                'group_id'   => $this->input->post('group') ? $this->input->post('group') : '2',
            ];
            $active = $this->input->post('status');
        }
        if ($this->form_validation->run() == true && $this->ion_auth->register($username, $password, $email, $additional_data, $active, $notify)) {
            $this->session->set_flashdata('message', $this->ion_auth->messages());
            redirect('auth/users');
        } else {
            $this->data['error']      = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('error')));
            $this->data['groups']     = $this->ion_auth->groups()->result_array();
            $this->data['stores']     = $this->site->getAllStores();
            $this->data['page_title'] = lang('add_user');
            $bc                       = [['link' => site_url('users'), 'page' => lang('users')], ['link' => '#', 'page' => lang('add_user')]];
            $meta                     = ['page_title' => lang('add_user'), 'bc' => $bc];
            $this->page_construct('auth/create_user', $this->data, $meta);
        }
    }

    public function deactivate($id = null)
    {
        if (!$this->Admin) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }
        $id = $this->config->item('use_mongodb', 'ion_auth') ? (string) $id : (int) $id;
        $this->form_validation->set_rules('confirm', lang('confirm'), 'required');

        if ($this->form_validation->run() == false) {
            if ($this->input->post('deactivate')) {
                $this->session->set_flashdata('error', validation_errors());
                redirect($_SERVER['HTTP_REFERER']);
            } else {
                $this->data['csrf']     = $this->_get_csrf_nonce();
                $this->data['user']     = $this->ion_auth->user($id)->row();
                $this->data['modal_js'] = $this->site->modal_js();
                $this->load->view($this->theme . 'auth/deactivate_user', $this->data);
            }
        } else {
            if ($this->input->post('confirm') == 'yes') {
                if ($id != $this->input->post('id')) {
                    show_error(lang('error_csrf'));
                }

                if ($this->ion_auth->logged_in() && $this->Admin) {
                    $this->ion_auth->deactivate($id);
                    $this->session->set_flashdata('message', $this->ion_auth->messages());
                }
            }

            redirect($_SERVER['HTTP_REFERER']);
        }
    }

    public function delete($id = null)
    {
        if (DEMO) {
            $this->session->set_flashdata('error', lang('disabled_in_demo'));
            redirect($_SERVER['HTTP_REFERER'] ?? 'welcome');
        }
        if (!$this->Admin) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }

        if ($this->input->get('id')) {
            $id = $this->input->get('id');
        }

        if ($this->auth_model->delete_user($id)) {
            $this->session->set_flashdata('message', lang('user_deleted'));
            redirect($_SERVER['HTTP_REFERER']);
        }
    }

    public function edit_user($id = null)
    {
        if ($this->input->post('id')) {
            $id = $this->input->post('id');
        }
        $this->data['title'] = lang('edit_user');

        if (!$this->loggedIn || !$this->Admin && $id != $this->session->userdata('user_id')) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }

        $user = $this->ion_auth->user($id)->row();

        if ($user->username != $this->input->post('username')) {
            $this->form_validation->set_rules('username', lang('username'), 'trim|is_unique[users.username]');
        }
        if ($user->email != $this->input->post('email')) {
            $this->form_validation->set_rules('email', lang('email'), 'trim|is_unique[users.email]');
        }

        if ($this->form_validation->run() === true) {
            if (DEMO) {
                $this->session->set_flashdata('error', lang('disabled_in_demo'));
                redirect($_SERVER['HTTP_REFERER'] ?? 'welcome');
            }
            if ($this->Admin) {
                if ($id == $this->session->userdata('user_id')) {
                    $data = [
                        'first_name' => $this->input->post('first_name'),
                        'last_name'  => $this->input->post('last_name'),
                        'phone'      => $this->input->post('phone'),
                        'gender'     => $this->input->post('gender'),
                    ];
                } else {
                    $data = [
                        'first_name' => $this->input->post('first_name'),
                        'last_name'  => $this->input->post('last_name'),
                        'username'   => $this->input->post('username'),
                        'email'      => $this->input->post('email'),
                        'phone'      => $this->input->post('phone'),
                        'gender'     => $this->input->post('gender'),
                        'active'     => $this->input->post('status'),
                        'group_id'   => $this->input->post('group'),
                        'store_id'   => $this->input->post('group') == 1 ? null : $this->input->post('store_id'),
                    ];
                }
            } else {
                $data = [
                    'first_name' => $this->input->post('first_name'),
                    'last_name'  => $this->input->post('last_name'),
                    'phone'      => $this->input->post('phone'),
                    'gender'     => $this->input->post('gender'),
                ];
            }

            if ($this->Admin) {
                if ($this->input->post('password')) {
                    $this->form_validation->set_rules('password', lang('edit_user_validation_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|max_length[' . $this->config->item('max_password_length', 'ion_auth') . ']|matches[password_confirm]');
                    $this->form_validation->set_rules('password_confirm', lang('edit_user_validation_password_confirm_label'), 'required');

                    $data['password'] = $this->input->post('password');
                }
            }
            //$this->sma->print_arrays($data);
        }
        if ($this->form_validation->run() === true && $this->ion_auth->update($user->id, $data)) {
            $this->session->set_flashdata('message', lang('user_updated'));
            redirect('auth/profile/' . $id);
        } else {
            $this->session->set_flashdata('error', validation_errors());
            redirect($_SERVER['HTTP_REFERER']);
        }
    }

    public function forgot_password()
    {
        $this->form_validation->set_rules('forgot_email', lang('email_address'), 'required|valid_email');

        if ($this->form_validation->run() == false) {
            $error = validation_errors() ? validation_errors() : $this->session->flashdata('error');
            $this->session->set_flashdata('error', $error);
            redirect('login#forgot_password');
        } else {
            $identity = $this->ion_auth->where('email', strtolower($this->input->post('forgot_email')))->users()->row();
            if (empty($identity)) {
                $this->ion_auth->set_message('forgot_password_email_not_found');
                $this->session->set_flashdata('error', $this->ion_auth->messages());
                redirect('login#forgot_password');
            }

            $forgotten = $this->ion_auth->forgotten_password($identity->email);

            if ($forgotten) {
                $this->session->set_flashdata('message', $this->ion_auth->messages());
                redirect('login#forgot_password');
            } else {
                $this->session->set_flashdata('error', $this->ion_auth->errors());
                redirect('login#forgot_password');
            }
        }
    }

    public function index()
    {
        if (!$this->loggedIn) {
            redirect('login');
        } elseif ($this->Admin) {
            redirect('admin');
        } else {
            redirect('index');
        }
    }

    //log the user in
    public function login($m = null)
    {
        if (!$m) {
            $m = $this->input->get('m');
        }

        if ($this->Settings->captcha) {
            $this->form_validation->set_rules('captcha', lang('captcha'), 'required|callback_captcha_check');
        }

        if ($this->form_validation->run() == true) {
            $remember = (bool) $this->input->post('remember');

            if ($this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember)) {
                if ($this->Settings->mmode) {
                    if (!$this->ion_auth->in_group('admin')) {
                        $this->session->set_flashdata('error', lang('site_is_offline_plz_try_later'));
                        redirect('auth/logout');
                    }
                }

                $this->session->set_flashdata('message', $this->ion_auth->messages());
                redirect($this->session->userdata('store_id') ? 'pos' : 'welcome');
            } else {
                $this->session->set_flashdata('error', $this->ion_auth->errors());
                sleep(2);
                redirect('login');
            }
        } else {
            $this->data['error']   = (validation_errors()) ? validation_errors() : $this->session->flashdata('error');
            $this->data['message'] = $this->session->flashdata('message') ? $this->session->flashdata('message') : ($m ? lang($m) : '');
            if ($this->Settings->captcha) {
                $this->load->helper('captcha');
                $vals = [
                    'img_path'   => './uploads/captcha/',
                    'img_url'    => site_url() . 'uploads/captcha/',
                    'img_width'  => 150,
                    'img_height' => 34,
                ];
                $cap     = create_captcha($vals);
                $capdata = [
                    'captcha_time' => $cap['time'],
                    'ip_address'   => $this->input->ip_address(),
                    'word'         => $cap['word'],
                ];

                $query = $this->db->insert_string('captcha', $capdata);
                $this->db->query($query);
                $this->data['image']   = $cap['image'];
                $this->data['captcha'] = ['name' => 'captcha',
                    'id'                         => 'captcha',
                    'type'                       => 'text',
                    'class'                      => 'form-control',
                    'required'                   => 'required',
                    'placeholder'                => lang('type_captcha'),
                ];
            }
            $this->data['page_title'] = lang('login');

            $this->load->view($this->theme . 'auth/login', $this->data);
        }
    }

    public function logout($m = null)
    {
        $logout = $this->ion_auth->logout();
        $this->session->set_flashdata('message', $this->ion_auth->messages());

        redirect('login?m=' . ($m ? $m : ($this->input->get('m') ? $this->input->get('m') : '')));
    }

    public function profile($id = null)
    {
        if (!$this->ion_auth->logged_in() || !$this->Admin && $id != $this->session->userdata('user_id')) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }
        if (!$id || empty($id)) {
            redirect('auth');
        }

        $this->data['title'] = lang('profile');

        $user                 = $this->ion_auth->user($id)->row();
        $groups               = $this->ion_auth->groups()->result_array();
        $this->data['csrf']   = $this->_get_csrf_nonce();
        $this->data['user']   = $user;
        $this->data['groups'] = $groups;

        $this->data['error']    = (validation_errors()) ? validation_errors() : $this->session->flashdata('error');
        $this->data['password'] = [
            'name'  => 'password',
            'id'    => 'password',
            'class' => 'form-control',
            'type'  => 'password',
            'value' => '',
        ];
        $this->data['password_confirm'] = [
            'name'  => 'password_confirm',
            'id'    => 'password_confirm',
            'class' => 'form-control',
            'type'  => 'password',
            'value' => '',
        ];
        $this->data['min_password_length'] = $this->config->item('min_password_length', 'ion_auth');
        $this->data['old_password']        = [
            'name'  => 'old',
            'id'    => 'old',
            'class' => 'form-control',
            'type'  => 'password',
        ];
        $this->data['new_password'] = [
            'name'    => 'new',
            'id'      => 'new',
            'type'    => 'password',
            'class'   => 'form-control',
            'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
        ];
        $this->data['new_password_confirm'] = [
            'name'    => 'new_confirm',
            'id'      => 'new_confirm',
            'type'    => 'password',
            'class'   => 'form-control',
            'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
        ];
        $this->data['user_id'] = [
            'name'  => 'user_id',
            'id'    => 'user_id',
            'type'  => 'hidden',
            'value' => $user->id,
        ];

        $this->data['id']         = $id;
        $this->data['stores']     = $this->site->getAllStores();
        $this->data['page_title'] = lang('profile');
        $bc                       = [['link' => site_url('users'), 'page' => lang('users')], ['link' => '#', 'page' => lang('profile')]];
        $meta                     = ['page_title' => lang('profile'), 'bc' => $bc];
        $this->page_construct('auth/profile', $this->data, $meta);
    }

    public function reload_captcha()
    {
        $this->load->helper('captcha');
        $vals = [
            'img_path'   => './uploads/captcha/',
            'img_url'    => site_url() . 'uploads/captcha/',
            'img_width'  => 150,
            'img_height' => 34,
        ];
        $cap     = create_captcha($vals);
        $capdata = [
            'captcha_time' => $cap['time'],
            'ip_address'   => $this->input->ip_address(),
            'word'         => $cap['word'],
        ];
        $query = $this->db->insert_string('captcha', $capdata);
        $this->db->query($query);

        echo $cap['image'];
    }

    public function reset_password($code = null)
    {
        if (!$code) {
            show_404();
        }

        $user = $this->ion_auth->forgotten_password_check($code);

        if ($user) {
            $this->form_validation->set_rules('new', lang('password'), 'required|min_length[8]|max_length[25]|matches[new_confirm]');
            $this->form_validation->set_rules('new_confirm', lang('confirm_password'), 'required');

            if ($this->form_validation->run() == false) {
                $this->data['error']               = (validation_errors()) ? validation_errors() : $this->session->flashdata('error');
                $this->data['message']             = $this->session->flashdata('message');
                $this->data['title']               = lang('reset_password');
                $this->data['min_password_length'] = $this->config->item('min_password_length', 'ion_auth');
                $this->data['new_password']        = [
                    'name'    => 'new',
                    'id'      => 'new',
                    'type'    => 'password',
                    'class'   => 'form-control',
                    'pattern' => '^.{8}.*$',
                ];
                $this->data['new_password_confirm'] = [
                    'name'    => 'new_confirm',
                    'id'      => 'new_confirm',
                    'type'    => 'password',
                    'class'   => 'form-control',
                    'pattern' => '^.{8}.*$',
                ];
                $this->data['user_id'] = [
                    'name'  => 'user_id',
                    'id'    => 'user_id',
                    'type'  => 'hidden',
                    'value' => $user->id,
                ];
                $this->data['csrf']           = $this->_get_csrf_nonce();
                $this->data['code']           = $code;
                $this->data['identity_label'] = $user->email;
                $this->data['page_title']     = lang('reset_password');
                $this->load->view($this->theme . 'auth/reset_password', $this->data);
            } else {
                if ($this->_valid_csrf_nonce() === false || $user->id != $this->input->post('user_id')) {
                    $this->ion_auth->clear_forgotten_password_code($code);
                    show_error(lang('error_csrf'));
                } else {
                    $identity = $user->email;

                    $change = $this->ion_auth->reset_password($identity, $this->input->post('new'));

                    if ($change) {
                        $this->session->set_flashdata('message', $this->ion_auth->messages());
                        redirect('login');
                    } else {
                        $this->session->set_flashdata('error', $this->ion_auth->errors());
                        redirect('auth/reset_password/' . $code);
                    }
                }
            }
        } else {
            $this->session->set_flashdata('error', $this->ion_auth->errors());
            redirect('login#forgot_password');
        }
    }

    public function update_avatar($id = null)
    {
        if ($this->input->post('id')) {
            $id = $this->input->post('id');
        }

        if (!$this->loggedIn || !$this->Admin && $id != $this->session->userdata('user_id')) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }

        //validate form input
        $this->form_validation->set_rules('avatar', lang('avatar'), 'trim');

        if ($this->form_validation->run() == true) {
            if ($_FILES['avatar']['size'] > 0) {
                $this->load->library('upload');
                $config['upload_path']   = 'uploads/avatars';
                $config['allowed_types'] = 'gif|jpg|png';
                $config['max_size']      = 1024;
                $config['max_width']     = 600;
                $config['max_height']    = 600;
                $config['overwrite']     = false;
                $config['encrypt_name']  = true;
                $config['max_filename']  = 25;
                $this->upload->initialize($config);

                if (!$this->upload->do_upload('avatar')) {
                    $error = $this->upload->display_errors();
                    $this->session->set_flashdata('error', $error);
                    redirect($_SERVER['HTTP_REFERER']);
                }

                $photo = $this->upload->file_name;

                $this->load->helper('file');
                $this->load->library('image_lib');
                $config['image_library']  = 'gd2';
                $config['source_image']   = 'uploads/avatars/' . $photo;
                $config['new_image']      = 'uploads/avatars/thumbs/' . $photo;
                $config['maintain_ratio'] = true;
                $config['width']          = 100;
                $config['height']         = 100;

                $this->image_lib->clear();
                $this->image_lib->initialize($config);
                if (!$this->image_lib->resize()) {
                    echo $this->image_lib->display_errors();
                }
                $user = $this->ion_auth->user($id)->row();
            } else {
                $this->form_validation->set_rules('avatar', lang('avatar'), 'required');
            }
        }

        if ($this->form_validation->run() == true && $this->auth_model->updateAvatar($id, $photo)) {
            // unlink('uploads/avatars/' . $user->avatar);
            // unlink('uploads/avatars/thumbs/' . $user->avatar);
            $this->session->set_userdata('avatar', $photo);
            $this->session->set_flashdata('message', lang('avatar_updated'));
            redirect($_SERVER['HTTP_REFERER']);
        } else {
            $this->session->set_flashdata('error', validation_errors());
            redirect($_SERVER['HTTP_REFERER']);
        }
    }

    public function users()
    {
        if (!$this->loggedIn) {
            redirect('login');
        }
        if (!$this->Admin) {
            $this->session->set_flashdata('warning', lang('access_denied'));
            redirect($_SERVER['HTTP_REFERER']);
        }

        $this->data['error']      = (validation_errors()) ? validation_errors() : $this->session->flashdata('error');
        $this->data['users']      = $this->site->getAllUsers();
        $bc                       = [['link' => '#', 'page' => lang('users')]];
        $meta                     = ['page_title' => lang('users'), 'bc' => $bc];
        $this->data['page_title'] = lang('users');
        $this->page_construct('auth/index', $this->data, $meta);
    }
}
