<?php

namespace App\Controllers\Panel\Users;

use App\Controllers\Panel\BC;
use App\Models\Panel\MasterData\Kelas;
use App\Models\Panel\RoleModel;
use App\Models\Panel\User\StaffModel;
use CodeIgniter\API\ResponseTrait;
use ZipArchive;

class Staff extends BC
{
    use ResponseTrait;
    private $staffModel;
    public function __construct()
    {
        parent::__construct();
        $this->staffModel = new StaffModel();
    }
    public function index()
    {
        return view('Panel/Users/Staff/index', ['page_title' => "Staff"]);
    }
    public function all()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $opt = [];
        if (!in_array($this->request->getGet('role'), ['all', null])) {
            $opt['role'] = explode(',', $this->request->getGet('role'));
            if (!user()->hasRole('admin') && strpos($this->request->getGet('role'), "admin") !== false) {
                foreach ($opt['role'] as $k => $role) {
                    if ($role == 'admin') unset($opt['role'][$k]);
                }
            }
        }
        $guru = $this->staffModel->getAll($opt);
        return $this->respond(['data' => $guru]);
    }
    public function detail($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $guru = $this->staffModel->findId($id);
        return $this->respond(['data' => $guru]);
    }

    public function delete($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $state = $this->staffModel->deleteId($id);
        if ($state) db_connect()->table('jadwal_diskusi')->where(['user_id' => $id, 'user_type' => 'staff'])->delete();
        return $this->respond(['deleted' => $state, 'message' => $state ? "Berhasil Menghapus" : "Gagal Menghapus"]);
    }

    public function add()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }

        $rules['username'] = [
            "alias" => "Username",
            'rules' => 'alpha_dash|max_length[128]|is_unique[users.username]',
            'errors' => [
                'alpha_dash' => 'Karakter Tidak Valid',
                'max_length' => 'Maksimal 128 Karakter',
                'is_unique' => '"{value}" Sudah Ada'
            ]
        ];
        $rules['fullname'] = [
            "alias" => "Nama Lengkap",
            'rules' => 'string|max_length[255]',
            'errors' => [
                'string' => '{value} Karakter Tidak Valid',
                'max_length' => '{value} Maksimal 255 Karakter'
            ]
        ];
        $rules['phone'] = [
            "alias" => "Nomor Handphone",
            'rules' => "integer|max_length[20]|permit_empty",
            'errors' => [
                'integer' => '{value} Nomor Tidak Valid,Pastikan Hanya Angka',
                'max_length' => '{value} Maksimal 20 Karakter',
            ]
        ];
        $rules['password'] = [
            "alias" => "Password",
            'rules' => 'string|min_length[4]|max_length[64]',
            'errors' => [
                'string' => 'Karakter Tidak Valid',
                'min_length' => 'Minimal 4 Karakter',
                'max_length' => 'Maksimal 64 Karakter'
            ]
        ];
        $rules['role'] = [
            "alias" => "Peran",
            'rules' => "string",
            'errors' => [
                'string' => 'Karakter Tidak Valid',
            ]
        ];
        $rules['status'] = [
            "alias" => "Status",
            'rules' => 'integer|in_list[1,0]',
            'errors' => [
                'integer' => 'Karakter Tidak Valid',
                'in_list' => 'Status Tidak Valid',
            ]
        ];
        if (!$this->validate($rules)) {
            $errors = $this->validator->getErrors();
            $err = '';
            foreach ($errors as $key => $error) {
                $err = $err . $rules[$key]['alias'] . " : " . $error . '<br>';
            }
            return $this->fail(["csrf" => csrf_hash(), 'message' => $err]);
        }
        $attendance_solution_id = $this->request->getVar('attendance_solution_id');
        if ($attendance_solution_id) {
            $sql = "SELECT IFNULL(ms.nama,u.fullname) fullname ,IFNULL(ms.nomor_induk,u.nomor_induk) nomor_induk";
            $sql .= ",IFNULL(ms.id,u.id) id,(CASE WHEN ms.id IS NULL THEN 1 ELSE 2 END) utype FROM (SELECT '$attendance_solution_id' as attendance_solution_id) as rftb";
            $sql .= " LEFT JOIN m_siswa ms ON rftb.attendance_solution_id=ms.attendance_solution_id LEFT JOIN users u ON rftb.attendance_solution_id=u.attendance_solution_id HAVING nomor_induk IS NOT NULL";
            $registered = db_connect()->query($sql)->getRowArray();
            if ($registered) {
                $msg = ["csrf" => csrf_hash(), 'message' => "Solution ID sudah terdaftar"];
                if ($registered['utype'] == 1) {
                    $msg['message'] .= " pada staff dengan nomor induk $registered[nomor_induk]";
                } else {
                    $msg['message'] .= " pada siswa dengan nomor induk $registered[nomor_induk]";
                }
                return $this->fail($msg);
            }
        }
        $rfid = $this->request->getVar('rfid');
        if ($rfid) {
            $sql = "SELECT IFNULL(ms.nama,u.fullname) fullname ,IFNULL(ms.nomor_induk,u.nomor_induk) nomor_induk";
            $sql .= ",IFNULL(ms.id,u.id) id,(CASE WHEN ms.id IS NULL THEN 1 ELSE 2 END) utype FROM (SELECT '$rfid' as rfid) as rftb";
            $sql .= " LEFT JOIN m_siswa ms ON rftb.rfid=ms.rfid LEFT JOIN users u ON rftb.rfid=u.rfid HAVING nomor_induk IS NOT NULL";
            $registered = db_connect()->query($sql)->getRowArray();
            if ($registered) {
                $msg = ["csrf" => csrf_hash(), 'message' => "RFID sudah terdaftar"];
                if ($registered['utype'] == 1) {
                    $msg['message'] .= " pada staff dengan nomor induk $registered[nomor_induk]";
                } else {
                    $msg['message'] .= " pada siswa dengan nomor induk $registered[nomor_induk]";
                }
                return $this->fail($msg);
            }
        }
        $user = new \App\Entities\Panel\User();

        $fullname = $this->request->getVar('fullname');
        $username = $this->request->getVar('username');
        $password = $this->request->getVar('password');
        $phone = $this->request->getVar('phone');
        $status = $this->request->getVar('status');
        $nomor_induk = $this->request->getVar('nomor_induk');
        $role = explode(',', $this->request->getVar('role'));
        $validNomorInduk = false;
        $bypassNomorInduk = false;
        foreach (['guru', 'kepsek'] as $roleNomorInduk) {
            if (in_array($roleNomorInduk, $role) && $nomor_induk) {
                $validNomorInduk = true;
                break;
            }
        }
        foreach ($role as $key => $value) {
            if (in_array($value, ['karyawan', 'piket', 'pengawas'])) {
                $bypassNomorInduk = true;
                break;
            }
        }
        if (!$bypassNomorInduk) {
            if (!$validNomorInduk) {
                $msg = ["csrf" => csrf_hash(), 'message' => "Nomor Induk tidak valid"];
                return $this->fail($msg);
            } elseif (db_connect()->table('users')->where(['nomor_induk' => $nomor_induk])->get()->getRowArray()) {
                $msg = ["csrf" => csrf_hash(), 'message' => "Nomor Induk sudah terdaftar"];
                return $this->fail($msg);
            }
        }
        $data = [
            'username' => $username,
            'fullname' => $fullname,
            'phone' => "$phone",
            'status' => $status,
            'rfid' => $rfid,
            'attendance_solution_id' => $attendance_solution_id,
            'nomor_induk' => $nomor_induk,
            'role' => $role
        ];
        $user->fill($data);
        $user->setPassword($password);
        if ($this->request->getVar('kelas')) {
            $user->kelas = $this->request->getVar('kelas');
        }
        $state = $this->staffModel->tambah($user);
        if (!$state) return $this->fail(["csrf" => csrf_hash(), 'message' => 'Gagal Menambah User']);
        return $this->respond(["csrf" => csrf_hash(), 'message' => 'Berhasil Menambah User']);
    }

    public function edit($id)
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $rules['username'] = [
            "alias" => "Username",
            'rules' => "alpha_dash|max_length[128]|is_unique[users.username,id,$id]",
            'errors' => [
                'alpha_dash' => 'Karakter Tidak Valid',
                'max_length' => 'Maksimal 128 Karakter',
                'is_unique' => '"{value}" Sudah Ada'
            ]
        ];
        $rules['fullname'] = [
            "alias" => "Nama Lengkap",
            'rules' => 'string|max_length[255]',
            'errors' => [
                'string' => '{value} Karakter Tidak Valid',
                'max_length' => '{value} Maksimal 255 Karakter'
            ]
        ];
        $rules['phone'] = [
            "alias" => "Nomor Handphone",
            'rules' => "integer|max_length[20]|permit_empty",
            'errors' => [
                'integer' => '{value} Nomor Tidak Valid,Pastikan Hanya Angka',
                'max_length' => '{value} Maksimal 20 Karakter',
            ]
        ];
        if ($this->request->getVar('password')) {
            $rules['password'] = [
                "alias" => "Password",
                'rules' => 'string|min_length[4]|max_length[64]',
                'errors' => [
                    'string' => 'Karakter Tidak Valid',
                    'min_length' => 'Minimal 4 Karakter',
                    'max_length' => 'Maksimal 64 Karakter'
                ]
            ];
        }
        $rules['role'] = [
            "alias" => "Peran",
            'rules' => "string",
            'errors' => [
                'string' => 'Karakter Tidak Valid',
            ]
        ];
        $rules['status'] = [
            "alias" => "Status",
            'rules' => 'integer|in_list[1,0]',
            'errors' => [
                'integer' => 'Karakter Tidak Valid',
                'in_list' => 'Status Tidak Valid',
            ]
        ];
        if (!$this->validate($rules)) {
            $errors = $this->validator->getErrors();
            $err = '';
            foreach ($errors as $key => $error) {
                $err = $err . $rules[$key]['alias'] . " : " . $error . '<br>';
            }
            return $this->fail(["csrf" => csrf_hash(), 'message' => $err]);
        }

        $attendance_solution_id = $this->request->getVar('attendance_solution_id');
        if ($attendance_solution_id) {
            $sql = "SELECT IFNULL(ms.nama,u.fullname) fullname ,IFNULL(ms.nomor_induk,u.nomor_induk) nomor_induk";
            $sql .= ",IFNULL(ms.id,u.id) id,(CASE WHEN ms.id IS NULL THEN 1 ELSE 2 END) utype FROM (SELECT '$attendance_solution_id' as attendance_solution_id) as rftb";
            $sql .= " LEFT JOIN m_siswa ms ON rftb.attendance_solution_id=ms.attendance_solution_id LEFT JOIN users u ON rftb.attendance_solution_id=u.attendance_solution_id HAVING nomor_induk IS NOT NULL";
            $registered = db_connect()->query($sql)->getRowArray();
            if ($registered) {
                if ($registered['id'] != $id) {
                    $msg = ["csrf" => csrf_hash(), 'message' => "Solution ID sudah terdaftar"];
                    if ($registered['utype'] == 1) {
                        $msg['message'] .= " pada staff dengan nomor induk $registered[nomor_induk]";
                    } else {
                        $msg['message'] .= " pada siswa dengan nomor induk $registered[nomor_induk]";
                    }
                    return $this->fail($msg);
                }
            }
        }
        $rfid = $this->request->getVar('rfid');
        if ($rfid) {
            $sql = "SELECT IFNULL(ms.nama,u.fullname) fullname ,IFNULL(ms.nomor_induk,u.nomor_induk) nomor_induk";
            $sql .= ",IFNULL(ms.id,u.id) id,(CASE WHEN ms.id IS NULL THEN 1 ELSE 2 END) utype FROM (SELECT '$rfid' as rfid) as rftb";
            $sql .= " LEFT JOIN m_siswa ms ON rftb.rfid=ms.rfid LEFT JOIN users u ON rftb.rfid=u.rfid HAVING nomor_induk IS NOT NULL";
            $registered = db_connect()->query($sql)->getRowArray();
            if ($registered) {
                if ($registered['id'] != $id) {
                    $msg = ["csrf" => csrf_hash(), 'message' => "RFID sudah terdaftar"];
                    if ($registered['utype'] == 1) {
                        $msg['message'] .= " pada staff dengan nomor induk $registered[nomor_induk]";
                    } else {
                        $msg['message'] .= " pada siswa dengan nomor induk $registered[nomor_induk]";
                    }
                    return $this->fail($msg);
                }
            }
        }
        $user = new \App\Entities\Panel\User();
        $fullname = $this->request->getVar('fullname');
        $username = $this->request->getVar('username');
        $password = $this->request->getVar('password');
        $phone = $this->request->getVar('phone');
        $status = $this->request->getVar('status');
        $role = explode(',', $this->request->getVar('role'));
        $nomor_induk = $this->request->getVar('nomor_induk');
        $validNomorInduk = false;
        $bypassNomorInduk = false;
        foreach (['guru', 'kepsek'] as $roleNomorInduk) {
            if (in_array($roleNomorInduk, $role) && $nomor_induk) {
                $validNomorInduk = true;
                break;
            }
        }
        foreach ($role as $key => $value) {
            if (in_array($value, ['karyawan', 'piket', 'pengawas'])) {
                $bypassNomorInduk = true;
                break;
            }
        }
        if (!$bypassNomorInduk) {
            if (!$validNomorInduk) {
                $msg = ["csrf" => csrf_hash(), 'message' => "Nomor Induk tidak valid"];
                return $this->fail($msg);
            } elseif (db_connect()->table('users')->where(['id !=' => $id, 'nomor_induk' => $nomor_induk])->get()->getRowArray()) {
                $msg = ["csrf" => csrf_hash(), 'message' => "Nomor Induk sudah terdaftar"];
                return $this->fail($msg);
            }
        }
        $data = [
            'id' => $id,
            'username' => $username,
            'fullname' => $fullname,
            'phone' => "$phone",
            'status' => $status,
            'rfid' => $rfid,
            'attendance_solution_id' => $attendance_solution_id,
            'nomor_induk' => $nomor_induk,
            'role' => $role
        ];
        $user->fill($data);
        if ($password) $user->setPassword($password);
        if ($this->request->getVar('kelas')) {
            $user->kelas_id = $this->request->getVar('kelas');
        }
        $state = $this->staffModel->ubah($user);
        if (!$state) return $this->fail(["csrf" => csrf_hash(), 'message' => 'Gagal Mengubah User']);
        return $this->respond(["csrf" => csrf_hash(), 'message' => 'Berhasil Mengubah User']);
    }
    public function roles()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $roles = (new RoleModel())->select('name,description')->whereNotIn('name', ['admin'])->findAll();
        return $this->respond(['data' => $roles, 'csrf' => ['name' => csrf_token(), 'value' => csrf_hash(),]]);
    }
    public function kelas()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $kelas = (new Kelas())->findAll();
        return $this->respond(['data' => $kelas, 'csrf' => ['name' => csrf_token(), 'value' => csrf_hash(),]]);
    }

    public function import_view()
    {
        return view('Panel/Users/Staff/import', ['page_title' => "Import Data Guru"]);
    }

    public function import_run()
    {

        set_time_limit(0);
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $allowedFile = [
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',

            'application/zip',
            'application/x-zip-compressed',
            'multipart/x-zip',
            'application/octet-stream'
        ];
        $file = $this->request->getFile('file');
        if ($file->hasMoved()) return $this->failNotFound("File Tidak Ditemukan");
        if (!in_array($file->getMimeType(), $allowedFile)) return $this->failForbidden("Format Tidak Diizinkan");
        $photo = [];
        $filename = null;
        $isZip =  $file->getMimeType() != 'application/vnd.ms-excel' && $file->getMimeType() != 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        $path = WRITEPATH . 'uploads/dump';
        if ($isZip) {
            $za = new ZipArchive();
            $filePath = $file->getPath() . "/" . $file->getFilename();
            $path = "$path/{$file->getFilename()}";
            if (!file_exists("$path")) mkdir("$path", 0777, true);
            $za->open($filePath);
            $za->extractTo($path);
            $za->close();
            foreach (scandir("$path") as $key => $value) {
                if (in_array($value, ['.', '..'])) continue;
                if (is_dir("$path/$value") && $value != 'pegawai') continue;
                $n = explode('.', $value);
                if (end($n) == 'xlsx' || end($n) == 'xls') {
                    $filename = $value;
                } else if (is_dir("$path/$value") && $value == 'pegawai') {
                    foreach (scandir("$path/$value") as $sk => $sv) {
                        if (in_array($value, ['.', '..'])) continue;
                        if (is_dir("$path/$value/$sv")) continue;
                        $n = explode('.', $sv);
                        if (count($n) < 2) continue;
                        if (!in_array(end($n), ['jpg', 'png', 'jpeg'])) continue;
                        unset($n[count($n) - 1]);
                        $photo[implode('.', $n)] = $sv;
                    }
                }
            }
        } else {
            $filename = $file->getClientName();
            $file->move($path, null, true);
            rmbfe('php', $path);
        }
        if (!$filename) return $this->fail(['message' => "File Tidak Ditemukan", 'csrf' => csrf_hash()], 404);
        $file = "$path/$filename";
        $inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($file);
        $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
        $spreadsheet = $reader->load($file);
        $db = db_connect();
        $db->transStart();

        if ($spreadsheet->sheetNameExists("DATA_GURU")) {

            foreach ($spreadsheet->getSheetByName("DATA_GURU")->toArray() as $key => $value) {
                $nomor_induk = $value[1];
                if (!$nomor_induk) continue;
                $attendance_id = $value[2];
                $username = $value[3];
                $fullname = $value[4];
                $password = setPassword($value[5]);
                $roles = explode(',', $value[6]);
                $foto = 'profile-photo.png';
                $phone = $value[7];
                if (!$roles) return $this->failServerError('Peran Harus Isi');
                if ($key == 0) continue;
                $query = "INSERT INTO users (nomor_induk,attendance_solution_id,username,fullname,password_hash, phone, photo) SELECT * FROM (SELECT ? nomor_induk,? attendance_solution_id,? username,? fullname,? password_hash,? phone,? photo) AS tmp WHERE NOT EXISTS (SELECT username FROM users WHERE username = ?) LIMIT 1";
                $queryData = [$nomor_induk, $attendance_id, $username, $fullname, $password, $phone];
                if (isset($photo[$nomor_induk])) {
                    $photoSource = $photo[$nomor_induk];
                    $pn = explode('.', basename($photoSource));
                    $pn = uniqid() . '.' . end($pn);
                    $foto = $pn;
                    $queryData[] = $foto;
                    rename("$path/pegawai/$photoSource", FCPATH . config('app')->imgPath . '/users/' . $pn);
                } else {
                    $queryData[] = $foto;
                }
                $queryData[] = $username;
                $db->query($query, $queryData);
                $uid = $db->insertID();
                if ($db->affectedRows() < 1) {
                    $queryupdate = "UPDATE users SET attendance_solution_id=?,fullname=?,password_hash=?,phone=?,photo=? WHERE nomor_induk=?";
                    $queryData = [$attendance_id, $fullname, $password, $phone, $foto, $nomor_induk];
                    $db->query($queryupdate, $queryData);
                    $uid = $db->table('users')->where('nomor_induk', $nomor_induk)->select('id')->get()->getRowArray();
                    if (!$uid) continue;
                    $uid = $uid['id'];
                    $db->table('users_roles')->where('user_id', $uid)->delete();
                }
                foreach ($roles as $role) {
                    $db->query("INSERT INTO users_roles SET user_id=$uid, role_id=(SELECT id FROM roles WHERE name = '$role' LIMIT 1)");
                }
            }
        }


        $db->transComplete();
        if ($db->transStatus() === FALSE) return $this->failServerError('Gagal Mengimport,Periksa Lagi');
        helper('Panel/utils');
        if ($isZip) rrmdir($path);
        return $this->respond(['message' => 'Berhasil Mengimport']);
    }
    public function example($type)
    {
        switch ($type) {
            case 'zip':
                return $this->response->download($this->fileLocation['DATA_GURU.zip'], null);
                break;
            case 'excel':
                return $this->response->download($this->fileLocation['DATA_GURU.xlsx'], null);
                break;
        }
    }

    public function rfid()
    {
        if (!$this->request->isAJAX() && ENVIRONMENT != 'development') {
            exit('No direct script access allowed');
        }
        $rfid = options('rfid_latest');
        save_options('', 'rfid_latest');
        return $this->respond(["csrf" => csrf_hash(), 'rfid' => $rfid]);
    }
}
