<?php

namespace App\Models;

use App\Enums\EspecialidadeOdontologiaEnum;
use App\Enums\StatusAgendamentoAtendimentoEnum;
use App\Enums\TipoAgendamentoEnum;
use App\Notifications\ConfirmacaoAgendamentoNotification;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;

class AgendamentoAtendimento extends Model
{
    protected $table = 'agendamentos_atendimentos';

    public function agendavel()
    {
        return $this->morphTo();
    }

    public function motivoCancelamento()
    {
        return $this->belongsTo(MotivoCancelamentoAgendamento::class, 'motivo_cancelamento_id');
    }

    public function scopeDeTipo($query, TipoAgendamentoEnum $tipo)
    {
        return $query->where('tipo', 'ilike', $tipo->getName());
    }

    public function scopeComStatus($query, StatusAgendamentoAtendimentoEnum $status)
    {
        return $query->where('status', $status->getIndex());
    }

    public function scopeDoPrestador($query, PrestadorServico $prestador)
    {
        return $query->whereHas('prestadorServico', function ($query) use ($prestador) {
            return $query->where('id', $prestador->id);
        });
    }

    public function scopeDoServicoAtendimento($query, ServicoAtendimento $servico)
    {
        return $query->whereHas('servicoAtendimento', function ($query) use ($servico) {
            return $query->where('id', $servico->id);
        });
    }

    public function scopeBuscaPorTermo($query, $termo)
    {
        return $query->whereHasMorph('agendavel', [Servidor::class, Funcionario::class, Dependente::class], function ($query) use ($termo) {
            return $query->where('nome', 'ilike', "%$termo%");
        });
    }

    public function scopeNaoDesmarcado($query)
    {
        return $query->where('status', '!=', StatusAgendamentoAtendimentoEnum::desmarcou()->getIndex());
    }

    public function scopeDaPessoa($query, Pessoa $pessoa)
    {
        return $query->whereHasMorph('agendavel', [get_class($pessoa)], function ($query) use ($pessoa) {
            return $query->where('agendavel_id', $pessoa->id);
        });
    }

    public function scopeDeStatus($query, StatusAgendamentoAtendimentoEnum $status)
    {
        return $query->where('status', 'ilike', $status->getName());
    }

    public function scopeEmAbertoOuEsperandoRecepcao($query)
    {
        return $query->where('status', StatusAgendamentoAtendimentoEnum::aberto()->getIndex())
                     ->orWhere('status', StatusAgendamentoAtendimentoEnum::esperandoRecepcao()->getIndex());
    }

    public function scopeDeEspecialidade($query, EspecialidadeOdontologiaEnum $especialidade)
    {
        return $query->whereHas('prestadorServico', function ($query) use ($especialidade) {
            return $query->where('especialidade', $especialidade->getIndex());
        });
    }

    public function prestadorServico()
    {
        return $this->belongsTo(PrestadorServico::class, 'prestador_servico_id');
    }

    public function servicoAtendimento()
    {
        return $this->belongsTo(ServicoAtendimento::class, 'servico_atendimento_id');
    }

    public function atendimento()
    {
        if ($this->tipo->isOdontologico()) {
            return $this->hasOne(AtendimentoOdontologico::class);
        } else {
            return $this->hasOne(AtendimentoJuridico::class);
        }
    }

    public function respostasAnamnese()
    {
        return $this->hasMany(RespostaAnamnese::class, 'agendamento_atendimento_id');
    }

    public function foiAtendido()
    {
        return $this->status->isAtendido();
    }

    public function podeSerAtendido()
    {
        return $this->status->isAberto() || $this->status->isEsperandoRecepcao();
    }

    public function naoDesmarcou()
    {
        return $this->status != StatusAgendamentoAtendimentoEnum::desmarcou();
    }

    public function scopeEmAberto($query)
    {
        return $query->where('status', StatusAgendamentoAtendimentoEnum::aberto()->getIndex());
    }

    public function enviaSMSConfirmacao()
    {
        $this->agendavel->notify(new ConfirmacaoAgendamentoNotification($this));
    }

    public function getInicioAttribute()
    {
        if ($this->attributes['inicio'] instanceof Carbon) {
            return $this->attributes['inicio'];
        }

        return Carbon::create($this->attributes['inicio']);
    }

    public function setInicioAttribute($inicio)
    {
        if ($inicio instanceof Carbon) {
            $this->attributes['inicio'] = $inicio;
            return;
        }
        
        $this->attributes['inicio'] = Carbon::createFromFormat('d/m/Y G:i', $inicio);
    }

    public function getFimAttribute()
    {
        if ($this->attributes['fim'] instanceof Carbon) {
            return $this->attributes['fim'];
        }

        return Carbon::create($this->attributes['fim']);
    }

    public function setFimAttribute($fim)
    {
        if ($fim instanceof Carbon) {
            $this->attributes['fim'] = $fim;
            return;
        }
        
        $this->attributes['fim'] = Carbon::createFromFormat('d/m/Y G:i', $fim);
    }

    public function getStatusAttribute()
    {
        if (! isset($this->attributes['status'])) {
            return null;
        }

        return StatusAgendamentoAtendimentoEnum::make($this->attributes['status']);
    }

    public function setStatusAttribute(StatusAgendamentoAtendimentoEnum $status)
    {
        $this->attributes['status'] = $status->getIndex();
    }

    public function getTipoAttribute()
    {
        return TipoAgendamentoEnum::make($this->attributes['tipo']);
    }
}
