<?php

namespace App\Controllers;


use App\DAO\Filter\QueryFilterTranslator;
use App\DAO\Order\QueryOrder;
use App\Services\AgendaService;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use App\Validations\AgendaValidation;
use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;

class AgendaController extends BaseController
{
    public function registerAgenda () {
        if (!$this->validate(AgendaValidation::register())) {
            return $this->response->setJSON([
                'message' => 'Informe os dados corretamente.',
                'errors' => $this->validation->getErrors()
            ]);
        }
        $agenda_service_response = (new AgendaService())->registerAgenda($_POST);
        $response_messages = [
            ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro de conexão com o banco de dados.'
            ],
            ServiceResponseInterface::SUCESS => [
                'code' => ResponseInterface::HTTP_OK,
                'message' => 'A agenda foi cadastrada com sucesso.'
            ],
            ServiceResponseInterface::HAVE_CONFLICTS => [
                'code' => ResponseInterface::HTTP_BAD_REQUEST,
                'message' => 'Não foi possível cadastrar a agenda, pois foram detectados conflitos com horários já cadastrados.'
            ],
            ServiceResponseInterface::VALIDATION_PARAMS_ERROR => [
                'code' => ResponseInterface::HTTP_BAD_REQUEST,
                'message' => 'Informe os dados corretamente.'
            ],
            ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro interno do servidor.'
            ],
        ];
        return $this->getResponse($agenda_service_response, $response_messages);
    }

    public function registerMultipleAgenda () {
        if (!$this->validate(AgendaValidation::multipleRegister())) {
            return $this->response->setJSON([
                'message' => 'Informe os dados corretamente.',
                'errors' => $this->validation->getErrors()
            ]);
        }
        $agenda_service_response = (new AgendaService())->registerMultipleAgenda($_POST);
        $response_messages = [
            ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro de conexão com o banco de dados.'
            ],
            ServiceResponseInterface::VALIDATION_PARAMS_ERROR => [
                'code' => ResponseInterface::HTTP_BAD_REQUEST,
                'message' => 'Informe os dados corretamente.'
            ],
            ServiceResponseInterface::PARTIAL_SUCESS => [
                'code' => ResponseInterface::HTTP_OK,
                'message' => 'Alguns horários foram cadastrados com sucesso. Outros conflitaram com horários já cadastrados.'
            ],
            ServiceResponseInterface::HAVE_CONFLICTS => [
                'code' => ResponseInterface::HTTP_BAD_REQUEST,
                'message' => 'Não foi possível cadastrar os horários da agenda, pois todos os horários gerados conflitaram com horários já cadastrados no sistema.'
            ],
            ServiceResponseInterface::SUCESS => [
                'code' => ResponseInterface::HTTP_OK,
                'message' => 'Todos os horários foram cadastrados com sucesso.'
            ],
        ];
        return $this->getResponse($agenda_service_response, $response_messages);
    }

    public function getAgenda () : Response {
        $filters = $_GET;
        if (isset($filters['id_unidade']) && !$filters['id_unidade']) {
            unset($filters['id_unidade']);
        }
        $query_filter_collection = new QueryFilterCollection($filters, QueryFilterTranslator::agenda());
        $pagination = $this->getPaginationFromRequest();
        $query_order_collection = new QueryOrderCollection ();
        $query_order_collection->push(QueryOrder::builder()
            ->setTable('agenda')
            ->setNameParam('data')
            ->setDesc($_GET['sort'] === '-')
            ->build()
        );
        $query_order_collection->push(QueryOrder::builder()
            ->setTable('agenda')
            ->setNameParam('hora_inicio')
            ->setDesc($_GET['sort'] === '-')
            ->build()
        );
        $agenda_service_response = (new AgendaService())->getAgendaListByMedicoID($query_filter_collection, $pagination, $query_order_collection);
        $response_messages = [
            ServiceResponseInterface::SUCESS => [
                'code' => ResponseInterface::HTTP_OK,
                'message' => 'Os dados das agendas foram encontrados com sucesso.'
            ],
            ServiceResponseInterface::RECORD_NOT_FOUND => [
                'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
                'message' => 'Nenhum registro foi encontrado.'
            ],
            ServiceResponseInterface::SERVICE_INTERNAL_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro interno do servidor.'
            ],
            ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro interno do servidor.'
            ],
        ];
        return $this->getResponse($agenda_service_response, $response_messages);
    }

    public function deleteAgenda (int $id_agenda) : Response {
        $agenda_service_response = (new AgendaService())->deleteAgenda($id_agenda);
        $response_messages = [
            ServiceResponseInterface::SUCESS => [
                'code' => ResponseInterface::HTTP_OK,
                'message' => 'A exclusão foi efetuda com sucesso.'
            ],
            ServiceResponseInterface::RECORD_NOT_FOUND => [
                'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
                'message' => 'Nenhum registro foi encontrado.'
            ],
            ServiceResponseInterface::RECORD_IS_LINKED => [
                'code' => ResponseInterface::HTTP_BAD_REQUEST,
                'message' => 'Essa agenda está vinculada a outros cadastros do sistema. Portanto, não pode ser excluída.'
            ],
            ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro interno do servidor.'
            ],
        ];
        return $this->getResponse($agenda_service_response, $response_messages);
    }

    public function updateAgenda (int $id_agenda) : Response {
        if (!$this->validate(AgendaValidation::update())) {
            return $this->response->setJSON([
                'message' => 'Informe os dados corretamente.',
                'errors' => $this->validation->getErrors()
            ]);
        }
        $agenda_service_response = (new AgendaService())->updateAgenda($id_agenda, $_POST);
        $response_messages = [
            ServiceResponseInterface::DATABASE_CONNECTION_ERROR => [
                'code' => ResponseInterface::HTTP_INTERNAL_SERVER_ERROR,
                'message' => 'Erro de conexão com o banco de dados.'
            ],
            ServiceResponseInterface::RECORD_NOT_FOUND => [
                'code' => ResponseInterface::HTTP_PARTIAL_CONTENT,
                'message' => 'A agenda não foi encontrada.'
            ],
            ServiceResponseInterface::SUCESS => [
                'code' => ResponseInterface::HTTP_OK,
                'message' => 'Os dados da agenda foram atualizados com sucesso.'
            ],
            ServiceResponseInterface::VALIDATION_PARAMS_ERROR => [
                'code' => ResponseInterface::HTTP_BAD_REQUEST,
                'message' => 'Informe os dados corretamente.'
            ],
        ];
        return $this->getResponse($agenda_service_response, $response_messages);
    }

    public function getAgendaByUnidadeAndData()
    {
        $uri = explode('/', $_SERVER['REQUEST_URI']);
        $unidadeId = (int)$uri[4] ?? 0;
        $date = $uri[6] ?? '1900-01-01';
        if (!$unidadeId || $date === '1900-01-01') {
            return $this->response->setStatusCode(404);
        }
        $sql = <<<SQL
            SELECT
                a.id as agenda_id
                ,a.`data` as data
                ,a.hora_inicio hora_inicio
                ,a.hora_final hora_final 
                ,med.id as medico_id
                ,pf.nome as medico_nome
                ,id_unidade as unidade_id
                ,a.id_tipo_procedimento as tipo_procedimento_id 
                ,tp.descricao as tipo_procedimento_descricao
            FROM agenda a
            INNER JOIN medico med on med.id = a.id_medico  
            INNER JOIN profissional pro on pro.id = med.id_profissional
            INNER JOIN pessoa pes on pes.id = pro.id_pessoa
            INNER JOIN pessoa_fisica pf on pf.id_pessoa = pes.id
            INNER JOIN tipo_procedimento tp on tp.id = a.id_tipo_procedimento 
            LEFT JOIN agendamento ag on ag.id_agenda = a.id
            WHERE 1=1
                AND ag.id is null
                and a.id_unidade = :unidade_id:
                and a.`data` = :data:
            order by `data`, hora_inicio
        SQL;
        $data = db_connect()->query($sql, [
            'unidade_id' => $unidadeId,
            'data' => $date
        ])->getResultArray();
        return $this
            ->response
            ->setStatusCode(count($data) > 0 ? 200 : 404)
            ->setJSON([
                'message' => 'Dados encontrados com sucesso.',
                'data' => $data
            ]);
    }
}
