<?php namespace App\Models;

use App\Entities\Profissional\Profissional;
use App\Entities\Usuario\Usuario;
use App\Services\Service;
use App\Utils\ModelUtils;
use App\ViewModels\ProfissionalDetalhesViewModel\ProfissionalDetalhesViewModel;
use CodeIgniter\Model;

class ProfissionalModel extends ModelEntity
{
    protected $table = 'profissional';
    protected $primaryKey = 'id';
    protected $returnType = 'array';
    protected $allowedFields = [
        'id_pessoa',
        'adicionado_por',
        'alterado_por',
    ];
    protected $useSoftDeletes = false;
    protected $useTimestamps = true;
    protected $skipValidation = true;
    protected $createdField  = 'criado_em';
    protected $updatedField  = 'alterado_em';

    public function validateUsuarioProfissional(Usuario &$usuario) : bool {
        $email = $usuario->getEmail();
        $senha = $usuario->getSenha();
        $query = $this->validateUsuarioProfissionalQuery($email, $senha);
        $result_array = $query->getResultArray();
        $usuario_result = $result_array && count($result_array) ? $result_array[0] : null;
        if (isset($usuario_result)) {
            $usuario->setId($usuario_result['id']);
            $usuario->setEmailVerificadoEm(
                $usuario_result['email_verificado_em'] === '0000-00-00 00:00:00'
                    ? ''
                    : $usuario_result['email_verificado_em']
            );
        }
        return !!$usuario_result;
    }

    private function validateUsuarioProfissionalQuery (string $email, string $senha) {
        $sql = "
            select 
                usuario.id as id,
                usuario.ativo as ativo,
                usuario.email_verificado_em as email_verificado_em,
                usuario.foto as foto
            from usuario, pessoa, profissional
            where 
                email = ? and
                senha = ? and
                usuario.id_pessoa = pessoa.id and
                profissional.id_pessoa = pessoa.id and
                ativo = 1
            limit 1
        ";
        $binds = [$email, $senha];
        $query = $this->db->query($sql, $binds);
        return $query;
    }

    public function registerProfissional (Profissional &$profissional) : void {
        $profissional_data = $profissional->toArray();
        unset($profissional_data['id']);
        $id_new_profissional = $this->insert($profissional_data);
        $profissional->setId($id_new_profissional);
    }

//    Busca de profissional pelo id

    public function getProfissionalDataByID (int $profissional_id) : ?ProfissionalDetalhesViewModel {
        $query = $this->getProfissionalByIdQuery($profissional_id);
        return $this->getProfissionalByIdMapper($query);
    }
    private function getProfissionalByIdQuery($profissional_id) {
        $sql = "
            select 
                profissional.id as id,
                pessoa_fisica.nome as nome,
                pessoa_fisica.cpf as cpf,
                usuario.email as email,
                pessoa.telefone_1 as telefone_1,
                pessoa.telefone_2 as telefone_2,	
                substring(pessoa_fisica.data_nascimento, 1, 10) as data_nascimento,
                pessoa_fisica.genero as genero,
                endereco.cep as cep,
                endereco.complemento as complemento,
                endereco.numero as numero,
                endereco.referencias as referencias,
                cep.bairro as bairro,
                cep.cidade as cidade,
                cep.estado as estado,
                cep.logradouro as logradouro
            from profissional, pessoa, pessoa_fisica, endereco, cep, usuario
            where 
                profissional.id_pessoa = pessoa.id and
                pessoa_fisica.id_pessoa = pessoa.id and
                endereco.id = pessoa.id_endereco and
                cep.id = endereco.cep and
                usuario.id_pessoa = pessoa.id and 
                usuario.ativo = 1 and
                profissional.id = ?
            limit 1
        ";
        $binds = [$profissional_id];
        $query = $this->db->query($sql, $binds);
        return $query;
    }

    private function getProfissionalByIdMapper ($query) : ?ProfissionalDetalhesViewModel {
        $result_array = $query->getResultArray();
        if (count($result_array ?? [])) {
            $profissional_detalhes = $result_array[0];
            $profissional_detalhes_view_model = $this->profissionalDetalhesMapper($profissional_detalhes);
            return $profissional_detalhes_view_model;
        } else {
            return null;
        }
    }

//    Busca lista de profissionais
    public function getProfissionalsAll (array $request) {
        $query = $this->getProfissionaisAllFilterQuery($request);
        $per_page = $request['per_page'];
        $result_array = isset($per_page)
            ? $query->paginate($per_page)
            : $query->findAll();
        if (count($result_array ?? [])) {
            $result_array = array_map(function ($row) {
                if ($row['email_verificado_em'] === '0000-00-00') {
                    $row['email_verificado_em'] = null;
                }
                $profissional_detalhes_view_model = $this->profissionalDetalhesMapper($row);
                return $profissional_detalhes_view_model->toArray();
            }, $result_array);
            return [
                'profissionais' => $result_array,
                'pagination' => (new Service)->generatePaginationData($this->pager)
            ];
        } else {
            return null;
        }
    }

    private function getProfissionaisAllFilterQuery (array $request) {
        $query = $this->select('
            profissional.id as id,
            pessoa_fisica.nome as nome,
            pessoa_fisica.cpf as cpf,
            usuario.email as email,
            pessoa.telefone_1 as telefone_1,
            pessoa.telefone_2 as telefone_2,	
            substring(pessoa_fisica.data_nascimento, 1, 10) as data_nascimento,
            pessoa_fisica.genero as genero,
            endereco.cep as cep,
            endereco.complemento as complemento,
            endereco.numero as numero,
            endereco.referencias as referencias,
            cep.bairro as bairro,
            cep.cidade as cidade,
            cep.estado as estado,
            cep.logradouro as logradouro
        ')
        ->join('pessoa','profissional.id_pessoa = pessoa.id','inner')
        ->join('pessoa_fisica','pessoa_fisica.id_pessoa = pessoa.id','inner')
        ->join('usuario','usuario.id_pessoa = pessoa.id','inner')
        ->join('endereco','endereco.id = pessoa.id_endereco','inner')
        ->join('cep','cep.id = endereco.cep','inner')
        ->where($this->getProfissionaisAllFilterWhere($request))
        ->like($this->getProfissionaisAllFilterLike($request))
        ->orderBy($this->getProfissionaisAllOrder($request));
        return $query;
    }

    private function getProfissionaisAllOrder(array $request) : string {
        $refs = [
            'cpf' => 'pessoa_fisica.cpf',
            'nome' => 'pessoa_fisica.nome',
            'email' => 'usuario.email',
        ];
        $order_by = ModelUtils::generateSortBy($request, $refs);
        return $order_by;
    }

    private function getProfissionaisAllFilterWhere (array $request) : array {
        $refs = [
            'profissional.id' => 'id',
            'pessoa.id' => 'id_pessoa',
            'usuario.ativo' => 'ativo',
            'usuario.id_perfil' => 'perfil',
            'usuario.id' => 'id_usuario',
            'pessoa_fisica.genero' => 'genero',
            'pessoa_fisica.data_nascimento >=' => 'data_nascimento_min',
            'pessoa_fisica.data_nascimento <=' => 'data_nascimento_max',
        ];
        $where = ModelUtils::generateFilter($request, $refs);
        return $where;
    }

    private function getProfissionaisAllFilterLike (array $request) {
        $refs = [
            'pessoa_fisica.cpf' => 'cpf',
            'pessoa_fisica.rg' => 'rg',
            'pessoa_fisica.nome' => 'nome',
            'pessoa_fisica.telefone_1' => 'telefone_1',
            'pessoa_fisica.telefone_2' => 'telefone_2',
            'usuario.id' => 'id_usuario',
            'usuario.email' => 'email',
            'endereco.cep' => 'cep',
            'endereco.numero' => 'numero',
            'endereco.referencias' => 'referencias',
            'endereco.complemento' => 'complemento',
            'cep.cidade' => 'cidade',
            'cep.estado' => 'estado',
            'cep.logradouro' => 'logradouro',
            'cep.bairro' => 'bairro'
        ];
        $like = ModelUtils::generateFilter($request, $refs);
        return $like;
    }

    private function profissionalDetalhesMapper (array $row) : ProfissionalDetalhesViewModel {
        $profissional_detalhes_view_model = ProfissionalDetalhesViewModel::builder()
            ->setId($row['id'])
            ->setNome($row['nome'])
            ->setCpf($row['cpf'])
            ->setEmail($row['email'])
            ->setTelefone1($row['telefone_1'])
            ->setTelefone2($row['telefone_2'])
            ->setdatanascimento($row['data_nascimento'])
            ->setgenero($row['genero'])
            ->setcep($row['cep'])
            ->setcomplemento($row['complemento'])
            ->setnumero($row['numero'])
            ->setreferencias($row['referencias'])
            ->setbairro($row['bairro'])
            ->setcidade($row['cidade'])
            ->setestado($row['estado'])
            ->setlogradouro($row['logradouro'])
            ->build();
        return $profissional_detalhes_view_model;
    }
}
