<?php
class JWT
{
    const KEY = "hJK5tywhKG1Yx7ab3T1Y5eqJT";

    private $header;
    private $payload;
    private $signature;
    private $session;
    private $request;
    private $db;

    public function __construct($registry, $modulo){
        $this->session = $registry->get('session');
        $this->request = $registry->get('request');
        $this->db = $registry->get('db');

        if($modulo == 'store' and isset($this->session->data['token_store'])){

            $jwt = explode('.',$this->session->data['token_store']);

            $this->header = Crypto::descriptografarAES256($jwt[0], Crypto::CAES256);
            $this->payload = Crypto::descriptografarAES256($jwt[1], Crypto::CAES256);
            $this->signature = Crypto::descriptografarAES256($jwt[2], Crypto::CAES256);

            $this->validate('store');
        }else if($modulo == 'admin' and isset($this->session->data['token_jws'])){
            $jwt = explode('.',$this->session->data['token_jws']);

            $this->header = Crypto::descriptografarAES256($jwt[0], Crypto::CAES256);
            $this->payload = Crypto::descriptografarAES256($jwt[1], Crypto::CAES256);
            $this->signature = Crypto::descriptografarAES256($jwt[2], Crypto::CAES256);

            $this->validate('admin');
        }
    }

    private function signature(){
        return base64_encode(hash_hmac('sha256',".$this->header.$this->payload",self::KEY,true));
    }

    private function validate($module){

        if($this->signature === $this->signature()){

            if(isset($this->session->data['token_store']) and $this->session->data['token_store'] and $module == 'store'){
                $payload = array(
                    "sub"=> $this->getCustomerLoged('sub'),
                    "iss"=> $this->request->server['HTTP_HOST'],
                    "aud"=> $this->request->server['REMOTE_ADDR'],
                    "id" => $this->getIdEfutura()
                );
            }else if(isset($this->session->data['token_jws']) and $this->session->data['token_jws'] and $module == 'admin' and isset($this->request->get['token'])){
                $fingerprint = $this->getFingerprint([$this->getCustomerLoged('sub'), $this->getIdEfutura(), $this->request->server['HTTP_HOST']]);
                if (!$fingerprint) {
                    $this->logout();
                    return false;
                }

                $payload = array(
                    "sub"=> $this->getCustomerLoged('sub'),
                    "iss"=> $this->request->server['HTTP_HOST'],
                    "aud"=> $fingerprint,
                    "token"=> $this->request->get['token'],
                    "id" => $this->getIdEfutura()
                );
            }else{
                return false;
            }

            $this->payload = base64_encode(json_encode($payload));
            if($this->signature === $this->signature()){
                return true;
            }
        }
        $this->logout();
    }

    private function getIdEfutura(){
        $query = $this->db->query("SELECT idempresa FROM parametros_efutura");
        return $query->row['idempresa'];
    }

     public function getFingerprint($data = []) {
        $fingerprint = $_COOKIE['fingerprint'] ?? null;
        if (!$fingerprint) {
            return false;
        }
        foreach($data as $info) {
            $fingerprint.= $info;
        }
        return base64_encode($fingerprint);
    }

    private function logout(){
        $this->header = '';
        $this->payload = '';
        $this->signature = '';
    }

    public function sessionJwt($id,$host,$ip,$token = null){

        $this->header = base64_encode('{"alg": "HS256" , "typ": "JWT"}');

        if(!$token){
            $payload = array(
                "sub"=> $id,
                "iss"=> $host,
                "aud"=> $ip,
                "id" => $this->getIdEfutura()
            );
        }else{
            $payload = array(
                "sub"=> $id,
                "iss"=> $host,
                "aud"=> $ip,
                "token"=> $token,
                "id" => $this->getIdEfutura()
            );
            $this->session->data['token'] = $token;
        }

        $token_name = $token? 'token_jws':'token_store';

        $this->payload = base64_encode(json_encode($payload));
        $this->signature = $this->signature();

        $this->session->data[$token_name] = Crypto::criptografarAES256($this->header, Crypto::CAES256).".".Crypto::criptografarAES256($this->payload, Crypto::CAES256).".".Crypto::criptografarAES256($this->signature, Crypto::CAES256);
    }

    public function getCustomerLoged($inf){
        if (empty($this->payload)) {
            return 0; // Retorna 0 se $this->payload não estiver definido
        }
        
        $data = json_decode(base64_decode($this->payload));
        return isset($data->$inf)? $data->$inf: 0;
    }
}