<?php
class Functions extends Database{
    private $msg;
    private $result;

    public function checkUsername($username){
        //run sql
        $sql = "SELECT * FROM admin WHERE username = :username";
        $this->query($sql);
        //bind values
        $this->bind(':username', $username);
        //fetch data
        $this->result = $this->fetchSingle();
        //check if result fetching was successful
        if($this->result){
            return true;
        }else{
            return false;
        }
    }

    //password encryption
    public function Password_Encryption($password){
        $blowfish_hash_format = "$2y$12$00ok";
        $salt_length = 22;
        $salt = $this->generate_salt($salt_length);
        $formatting_blowfish_with_salt = $blowfish_hash_format.$salt;
        return crypt($password, $formatting_blowfish_with_salt);
    }

    //generate salt function
    public function generate_salt($length){
        $unique_random_string = md5(uniqid(mt_rand(), true));
        $base64_string = base64_encode($unique_random_string);
        $modified_base64_string = str_replace('+', '_', $base64_string);
        return substr($modified_base64_string, 0, $length);
    }
    //password check function//

    public function password_check($password, $existing_hash){
        $hash = crypt($password, $existing_hash);
        if($hash === $existing_hash){
            return true;
        }else{
            return false;
        }
    }

    //login check//
    public function loginCheck($username, $password){
        global $username;
        $sql = "SELECT * FROM admin WHERE username = '$username'";
        $this->query($sql);
        $username  = $this->fetchSingle();
        //check if email was found in database
        if($username){
            global  $existing_hash;
            $existing_hash = $username->password;//password already in database
            //check for password associated with same username
            if($this->password_check($password, $existing_hash)){
                return $username;
            }
        }else {
            return null;
        }
    }


    public function outPutmsg($msg){
        return $this->msg = $msg;
    }

    public function validate_phone($phone){
        $pattern = "/^[0]\d{10}$/";
        if(preg_match($pattern, $phone)){
            return true;
        }else{
            return false;
        }

    }

    /*
* slugify($text)
* Function to convert a text
* to slug (url-friendly version)
* @return slug string
*/
    public function slugify($text) {
        // covert to lowercase
        $word = strtolower($text);

        // remove excess whitespace
        $strippedWord = preg_replace('/\s\s+/', ' ', $word);

        // Replace strings
        $out = array(" ", "/", ".", "?", "(", ")", "$", "#", "&", "*", ",", "'", "\"", "“", "”", "\\", "+", "=", "%", "^");
        $slug = str_replace($out, "-", $strippedWord);

        // Remove cases of double "--"
        $newSlug = str_replace("--", "-", $slug);

        // Check if $out string is trailing at the end of the text
        if ( in_array(substr($newSlug, -1), $out) || substr($newSlug, -1) === "-") {
            $cleanedSlug = substr_replace($newSlug, "", -1);
        }
        else {
            $cleanedSlug = $newSlug;
        }

        return $cleanedSlug;
    }

    public function base_url(){
        $sql = "SELECT main_url FROM general_settings";
        $this->query($sql);
        return $this->fetchColumn()."/admin/";
    }

    public function student_url(){
        $sql = "SELECT main_url FROM general_settings";
        $this->query($sql);
        return $this->fetchColumn()."/student/";
    }

    public function teacher_url(){
        $sql = "SELECT main_url FROM general_settings";
        $this->query($sql);
        return $this->fetchColumn()."/teacher/";
    }

    public function main_url(){
        $sql = "SELECT main_url FROM general_settings";
        $this->query($sql);
        return $this->fetchColumn()."/";
    }


    //create function for password check

    public function Checkpassword($password){
        $password_pattern = preg_match("/(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/", $password);
        //password
        /*
         * Password must include one uppercase letter, one lowercase letter, one number,
         * and one special character such as $ or %
         * and length should be between 6 and 16
         */
        if($password_pattern){
            return true;
        }else{
            return false;
        }
    }

    public function generate_reg_no(){
        $sql = "SELECT reg_no_prefix FROM general_settings";
        $this->query($sql);
         $school_code = $this->fetchColumn() ."/";
         $min_no = 1000;
         $max_num = 9999;
         $year = date("Y");
         $random_no = rand($min_no, $max_num);
        return $school_code.$year.$random_no;

    }

    //validate admin privilege
    public function check_privilege($username, $module_name){
        $sql = "SELECT type FROM admin WHERE username =:username";
        $this->query($sql);
        $this->bind(":username", $username);
        $user_type = $this->fetchColumn();
        if($user_type == 'admin'){
            $sql = "SELECT module_name FROM admin_privileges WHERE module_name =:module_name";
            $this->query($sql);
            $this->bind( ":module_name", $module_name);
            $db_module_name = $this->fetchColumn();
            if($db_module_name == $module_name){
                return  true;
            }
        }elseif($user_type != 'admin'){
            return true;
        }



    }

    public function alert(){
        return 'You are not permitted to view this page. Pls contact Management';

    }

    /*

    Teacher Account Specific functions
    * The functions here are only specific to the teachers section of the application
    */

    //login check//
    public function teacherLoginCheck($username, $password){
        global $username;
        $sql = "SELECT * FROM teachers WHERE username = '$username'";
        $this->query($sql);
        $username  = $this->fetchSingle();
        //check if email was found in database
        if($username){
            global  $existing_hash;
            $existing_hash = $username->password;//password already in database
            //check for password associated with same username
            if($this->password_check($password, $existing_hash)){
                return $username;
            }
        }else {
            return null;
        }
    }


    /*

 Student Account Specific functions
 * The functions here are only specific to the students section of the application
 */

    //check for card serial no validity
    function cardSerial($card_serial){
        //query database
        $sql = "SELECT * FROM generated_pins WHERE pin = :card_serial";
        $this->query($sql);
        $this->bind(":card_serial", $card_serial);
        $rowCount = $this->rowCount();
        if($rowCount > 0 ){
            $result = $this->fetchSingle();
            while($result){
                $dbserial = $result->pin;
                if($card_serial == $dbserial){
                    return true;
                }else{
                    return false;
                }
            }

        }else{
            return false;
        }
    }

    //check if card serial  is available for use(first time use)
    function ifPinAvailableForUse($card_serial){
        $sql = "SELECT * FROM generated_pins WHERE pin = :card_serial && status = :open";
        $this->query($sql);
        $this->bind(":card_serial", $card_serial);
        $this->bind(":open", 'open');
        $row_count = $this->rowCount();
        if($row_count > 0){
            $result = $this->fetchSingle();
            $dbpin = $result->pin;
            // $db_expire_date = $result['expired_date'];
            if($card_serial == $dbpin){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    //check if card serial is in use by another user, or the same user and if it hasn't expired
    function ifPinStillExists($card_serial, $name, $current_date){
        $sql = "SELECT * FROM pins WHERE pin_code = :card_serial && status =:one && used_by = :name AND card_availability =:open";
        $this->query($sql);
        $one = 1;
        $this->bind(":card_serial", $card_serial);
        $this->bind(":one", $one);
        $this->bind(":name", $name);
        $this->bind(":open", 'open');
        $row_count = $this->rowCount();
        if($row_count > 0){
            $result = $this->fetchSingle();
            $dbpin = $result->pin_code;
            $dbName = $result->used_by;
            $db_card_expired = $result->expire_date;
            if($card_serial == $dbpin && $name == $dbName && $current_date < $db_card_expired){
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    //check if generated pin is valid or not
    function checkGeneratedPin($pin, $username){
        $sql = "SELECT exam_pin FROM student WHERE username =:username";
        $this->query($sql);
        $this->bind(":username", $username);
        $row_count = $this->rowCount();
        if($row_count > 0){
            $result = $this->fetchSingle();
            $dbpin = $result->exam_pin;
            if($pin == $dbpin){
                return true;
            }else{
                return false;
            }
        }
    }

    //login check//
    public function studentLoginCheck($username, $password){
        global $username;
        $sql = "SELECT * FROM student WHERE username = '$username'";
        $this->query($sql);
        $username  = $this->fetchSingle();
        //check if email was found in database
        if($username){
            global  $existing_hash;
            $existing_hash = $username->password;//password already in database
            //check for password associated with same username
            if($this->password_check($password, $existing_hash)){
                return $username;
            }
        }else {
            return null;
        }
    }

    public function regnoCheck($regno){
        $sql = "SELECT registerNO FROM student WHERE registerNO =:regno";
        $this->query($sql);
        $this->bind(":regno", $regno);
        $row_count = $this->rowCount();
        if($row_count > 0){
            return true;
        }else{
            return false;
        }
    }

    public function generateExamCode(): string
    {
        //generate a random exam code
        return bin2hex(random_bytes(4));
    }

}