<?php

namespace App\Controllers\Admin;

use App\Controllers\BaseController;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Shield\Entities\User;
use OpenSpout\Common\Entity\Cell;
use OpenSpout\Common\Entity\Row;
use OpenSpout\Common\Entity\Style\Style;
use OpenSpout\Writer\XLSX\Options;
use OpenSpout\Writer\XLSX\Writer;

class UserSetting extends BaseController
{
    use ResponseTrait;

    public function __construct()
    {
        $this->UsersModel = model('App\Models\Admin\UsersModel');
    }

    private function setJsonHeader()
    {
        return $this->response->setHeader('Content-Type', 'application/json');
    }

    //Validation Rule
    private function ruleUser($id = null)
    {
        return [
            'id'               => 'trim',
            'username'         => 'required|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]',
            'nip'              => $id 
                ? "required|is_unique[users.nip,id,{$id}]"
                : "required|is_unique[users.nip]",
            'unit'             => 'required|numeric',
            'jabatan'          => 'required|numeric',
            'id_kantor'        => 'permit_empty|numeric',
            'whatsapp'         => $id 
                ? "required|numeric|is_unique[users.whatsapp,id,{$id}]"
                : "required|numeric|is_unique[users.whatsapp]",
            'email'            => $id 
                ? "required|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]|max_length[254]|valid_email|is_unique[auth_identities.secret,user_id,{$id}]"
                : "required|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]|max_length[254]|valid_email|is_unique[auth_identities.secret,user_id]",
            'password'         => $id 
                ? 'permit_empty|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]|strong_password' // Tidak wajib saat update
                : 'required|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]|strong_password',    // Wajib saat insert
            'password_confirm' => $id
                ? [
                'label' => 'password confirm',
                'rules' => 'trim|permit_empty|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]|matches[password]', // Tidak wajib saat update
            ]
            : [
                'label' => 'password confirm',
                'rules' => 'trim|required|regex_match[/^[a-zA-Z0-9\s.,@-]+$/]|max_length[200]|matches[password]',     // Wajib saat insert
            ],
        ];
    }

    public function index()
    {
        //cek privilege dan link
        #REKAM---------
        if (priv_menu('user_setting', 'rekam')) {
            $rekam = 1;
            $link_rekam = base_url('admin/user_setting/new_user');
        } else {
            $rekam = 0;
            $link_rekam = '';
        }

        #UBAH----------
        if (priv_menu('user_setting', 'ubah')) {
            $ubah = 1;
            $link_ubah = base_url('admin/user_setting/edit_user/');
            $link_activate = base_url('admin/user_setting/activate');
            $link_deactivate = base_url('admin/user_setting/deactivate');
            $link_ban = base_url('admin/user_setting/ban');
            $link_unban = base_url('admin/user_setting/unban');
        } else {
            $ubah = 0;
            $link_ubah = '';
            $link_activate = '';
            $link_deactivate = '';
            $link_ban = '';
            $link_unban = '';
        }

        #HAPUS----------
        if (priv_menu('user_setting', 'hapus')) {
            $hapus = 1;
            $link_hapus = base_url('admin/user_setting/delete');
        } else {
            $hapus = 0;
            $link_hapus = '';
        }

        #EXPORT DLL----------
        if (priv_menu('user_setting', 'exp')) {
            $exp = 1;
            $link_exp = base_url('admin/user_setting/excel');
        } else {
            $exp = 0;
            $link_exp = '';
        }

        return view('admin/users/users_list', [
            'rekam' => $rekam,
            'link_rekam' => $link_rekam,
            'ubah' => $ubah,
            'link_ubah' => $link_ubah,
            'hapus' => $hapus,
            'link_hapus' => $link_hapus,
            'exp' => $exp,
            'link_exp' => $link_exp,
            'link_activate' => $link_activate,
            'link_deactivate' => $link_deactivate,
            'link_ban' => $link_ban,
            'link_unban' => $link_unban,
            'dd_pdk_unit' => $this->UsersModel->dd_pdk_unit(),
            'dd_pdk_jabatan' => $this->UsersModel->dd_pdk_jabatan(),
            'dd_pdk_satker' => $this->UsersModel->dd_pdk_satker(),
        ]);
    }

    public function datagrid()
    {
        $this->setJsonHeader();

        $page        = $this->request->getPost('page') ?: 1;
        $rows        = $this->request->getPost('rows') ?: 10;
        $sort        = $this->request->getPost('sort');
        $order       = $this->request->getPost('order');
        $filterRules = $this->request->getPost('filterRules');
        $start       = ($page - 1) * $rows;

        if ($sort && $order) {
            $sortOrder = multi_sort($sort, $order);
        } else {
            $sortOrder = null;
        }

        // save to session for export excel
        $sessionDatagrid = [
            'sortOrder'   => $sortOrder,
            'filterRules' => $filterRules,
        ];
        $this->session->set($sessionDatagrid);

        $datas = $this->UsersModel->get_rows($rows, $start, $filterRules, $sortOrder);

        foreach ($datas as $k => $v) {
            $users             = auth()->getProvider();
            $user              = $users->findById($v->id);
            
            $datas[$k]->id = encrypt_url($v->id);
            $datas[$k]->active = $v->active == 0 ? 'N':'Y';
        }

        $res['total'] = $this->UsersModel->get_total($filterRules);
        $res['rows']  = $datas;

        return $this->response->setJSON($res);
    }

    public function get_avatar()
    {
        $datax = $this->request->getPost('datax');
        if (! $datax) {
            exit('Data tidak ditemukan');
        }

        $res = download_ceisa($datax);
        if ($res && $res->getStatusCode() == '200') {
            $body = json_decode($res->getBody());

            if (!empty($body->data->base64)) {
                $avatar = 'data:image/png;base64, '.$body->data->base64;
            } else {
                $avatar = base_url('files/avatar/default.png');
            }
        } else {
            $avatar = base_url('files/avatar/default.png');
        }

        return $this->respond(['avatar' => $avatar]);
    }

    //FUNGSI REKAM---------------------
    //Tampilkan Form untuk Rekam User
    public function new_user()
    {
        if (priv_menu('user_setting', 'rekam')) {
            return view('admin/users/users_form', [
                'action' => base_url('admin/user_setting/create'),
                'id' => '',
                'username' => '',
                'nip' => '',
                'email' => '',
                'whatsapp' => '',
                'unit' => '',
                'jabatan' => '',
                'id_kantor' => '',
                'dd_pdk_unit' => $this->UsersModel->dd_pdk_unit(),
                'dd_pdk_jabatan' => $this->UsersModel->dd_pdk_jabatan(),
                'dd_pdk_satker' => $this->UsersModel->dd_pdk_satker(),
            ]);
        } else {
            return $this->fail(['message' => NO_AKSES]);
        }
    }//End Tampilkan Form untuk Rekam

    public function create()
    {
        $this->setJsonHeader();
        $vrUser = $this->ruleUser();

        //jika tdk memiliki akses utk rekam data
        if (!priv_menu('user_setting', 'rekam')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect data form
        $data = [
            'username' => $this->request->getPost('username', FILTER_SANITIZE_SPECIAL_CHARS),
            'nip'      => $this->request->getPost('nip', FILTER_SANITIZE_SPECIAL_CHARS),
            'unit'     => $this->request->getPost('unit', FILTER_SANITIZE_NUMBER_INT),
            'jabatan'  => $this->request->getPost('jabatan', FILTER_SANITIZE_NUMBER_INT),
            'id_kantor'=> $this->request->getPost('id_kantor', FILTER_SANITIZE_NUMBER_INT),
            'whatsapp' => $this->request->getPost('whatsapp', FILTER_SANITIZE_SPECIAL_CHARS),
            'email'    => $this->request->getPost('email', FILTER_SANITIZE_SPECIAL_CHARS),
            'password' => $this->request->getPost('password', FILTER_SANITIZE_SPECIAL_CHARS),
        ];

        //jika validasi gagal
        if (!$this->validate($vrUser)) {
            return $this->fail($this->validator->getErrors(), 400);
        }

        //proses simpan
        $users = auth()->getProvider();
        $user = new User($data);
        $users->save($user);
        // To get the complete user object with ID, we need to get from the database
        $user = $users->findById($users->getInsertID());
        // Add to default group
        $users->addToDefaultGroup($user);

        return $this->respond(['message' => B_SIMPAN], 201);
    }//END REKAM ==================

    //FUNGSI UBAH---------------
    //Tampilkan Form Edit Menu
    public function edit_user($id)
    {
        $row = $this->UsersModel->find(decrypt_url($id));

        if (!$row) {
            exit('Data tidak ditemukan');
        }

        return view('admin/users/users_form', [
            'action' => base_url('admin/user_setting/update'),
            'id' => encrypt_url($row->id),
            'username' => $row->username,
            'nip' => $row->nip,
            'email' => $row->email,
            'whatsapp' => $row->whatsapp,
            'unit' => $row->unit,
            'jabatan' => $row->jabatan,
            'id_kantor' => $row->id_kantor ?? '',
            'dd_pdk_unit' => $this->UsersModel->dd_pdk_unit(),
            'dd_pdk_jabatan' => $this->UsersModel->dd_pdk_jabatan(),
            'dd_pdk_satker' => $this->UsersModel->dd_pdk_satker(),
        ]);
    }//End Tampilkan Form Edit Menu

    public function update()
    {
        $this->setJsonHeader();

        //jika tdk memiliki akses utk ubah data
        if (!priv_menu('user_setting', 'ubah')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect form data
        $id = decrypt_url($this->request->getPost('id'));
        $vrUser = $this->ruleUser($id);
        $data = [
            'id'       => $id,
            'username' => $this->request->getPost('username', FILTER_SANITIZE_SPECIAL_CHARS),
            'nip'      => $this->request->getPost('nip', FILTER_SANITIZE_SPECIAL_CHARS),
            'unit'     => $this->request->getPost('unit', FILTER_SANITIZE_NUMBER_INT),
            'jabatan'  => $this->request->getPost('jabatan', FILTER_SANITIZE_NUMBER_INT),
            'id_kantor'=> $this->request->getPost('id_kantor', FILTER_SANITIZE_NUMBER_INT),
            'whatsapp' => $this->request->getPost('whatsapp', FILTER_SANITIZE_SPECIAL_CHARS),
            'email'    => $this->request->getPost('email', FILTER_SANITIZE_SPECIAL_CHARS),
            'password' => $this->request->getPost('password', FILTER_SANITIZE_SPECIAL_CHARS),
        ];

        //jika validasi gagal
        if (!$this->validate($vrUser)) {
            return $this->fail($this->validator->getErrors(), 400);
        }

        //proses update
        $users = auth()->getProvider();

        $user = $users->findById($id);
        $user->fill($data);
        $users->save($user);

        return $this->respond(['message' => B_UBAH], 200);
    }//END UPDATE ==================

    public function activate()
    {
        $this->setJsonHeader();

        //jika tdk memiliki akses utk ubah data
        if (!priv_menu('user_setting', 'ubah')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect form data
        $ids = $this->request->getPost('ids');
        //proses update
        foreach ($ids as $id) {
            $users = auth()->getProvider();

            $user = $users->findById(decrypt_url($id));
            $user->activate();
        }

        return $this->respond(['message' => count($ids) . ' '.B_UBAH], 200);
    }

    public function deactivate()
    {
        $this->setJsonHeader();

        //jika tdk memiliki akses utk ubah data
        if (!priv_menu('user_setting', 'ubah')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect form data
        $ids = $this->request->getPost('ids');
        //proses update
        foreach ($ids as $id) {
            $users = auth()->getProvider();

            $user = $users->findById(decrypt_url($id));
            $user->deactivate();
        }

        return $this->respond(['message' => count($ids) . ' '.B_UBAH], 200);
    }

    public function ban()
    {
        $this->setJsonHeader();

        //jika tdk memiliki akses utk ubah data
        if (!priv_menu('user_setting', 'ubah')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect form data
        $ids    = $this->request->getPost('ids');
        $reason = $this->request->getPost('r');
        //proses update
        foreach ($ids as $id) {
            $users = auth()->getProvider();
            $user  = $users->findById(decrypt_url($id));
            $user->deactivate();
            $user->ban($reason);
        }

        return $this->respond(['message' => count($ids) .' '.B_UBAH], 200);
    }

    public function unban()
    {
        $this->setJsonHeader();

        //jika tdk memiliki akses utk ubah data
        if (!priv_menu('user_setting', 'ubah')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect form data
        $ids = $this->request->getPost('ids');
        //proses update
        foreach ($ids as $id) {
            $users = auth()->getProvider();
            $user  = $users->findById(decrypt_url($id));
            $user->unBan();
        }

        return $this->respond(['message' => count($ids) .' '.B_UBAH], 201);
    }

    public function delete()
    {
        $this->setJsonHeader();

        //jika tdk memiliki akses utk hapus data
        if (!priv_menu('user_setting', 'hapus')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //collect form data
        $ids = $this->request->getPost('ids');
        //proses delete
        foreach ($ids as $id) {
            $users = auth()->getProvider();
            $users->delete(decrypt_url($id), true);
        }

        return $this->respond(['message' => count($ids) .' '.B_HAPUS], 200);
    }

    public function excel($token, $limit)
    {
        //jika tdk memiliki akses utk ekspor data
        if (!priv_menu('user_setting', 'exp')) {
            return $this->fail(['message' => NO_AKSES], 403);
        }

        //proses ambil data dan ekspor
        $token_cek = encrypt_url(csrf_hash());

        if ($token_cek !== $token) {
            return $this->fail(['message' => NO_AKSES]);
        }

        delete_older_than(WRITEPATH . 'excel', 3600);
        $customTempFolderPath = WRITEPATH . 'excel/';
        $filePath             = WRITEPATH . 'excel/' . date('YmdHis') . '.xlsx';

        $sortOrder   = $this->session->sortOrder;
        $filterRules = $this->session->filterRules;

        $results = $this->UsersModel->get_excel((int) $limit, $filterRules, $sortOrder);

        $defaultStyle = new Style();
        $defaultStyle->setFontName('Arial');
        $defaultStyle->setFontSize(11);

        $options                    = new Options();
        $options->DEFAULT_ROW_STYLE = $defaultStyle;
        $options->setTempFolder($customTempFolderPath);

        $writer = new Writer($options);
        $writer->openToFile($filePath);

        // header
        $header = [
            Cell::fromValue('id'),
            Cell::fromValue('nama'),
            Cell::fromValue('nip'),
            Cell::fromValue('nama_sunit'),
            Cell::fromValue('nama_sjab'),
            Cell::fromValue('nama_kantor'),
            Cell::fromValue('whatsapp'),
            Cell::fromValue('status'),
            Cell::fromValue('status_message'),
            Cell::fromValue('active'),
            Cell::fromValue('last_active'),
            Cell::fromValue('created_at'),
            Cell::fromValue('updated_at'),
            Cell::fromValue('deleted_at'),
        ];

        $singleRow = new Row($header);
        $writer->addRow($singleRow);

        // cells
        foreach ($results as $res) {
            $cells = [
                Cell::fromValue((int) $res->id),
                Cell::fromValue($res->username),
                Cell::fromValue($res->nip),
                Cell::fromValue($res->nama_sunit),
                Cell::fromValue($res->nama_sjab),
                Cell::fromValue($res->nama_kantor),
                Cell::fromValue($res->whatsapp),
                Cell::fromValue($res->status),
                Cell::fromValue($res->status_message),
                Cell::fromValue((int) $res->active),
                Cell::fromValue($res->last_active),
                Cell::fromValue($res->created_at),
                Cell::fromValue($res->updated_at),
                Cell::fromValue($res->deleted_at),
            ];

            $singleRow = new Row($cells);
            $writer->addRow($singleRow);
        }

        $writer->close();

        return $this->response->download($filePath, null)->setFileName('Users-' . date('Ymd') . '-' . date('His') . '.xlsx');
        delete_files($filePath); 
    }
}