<?php namespace App\Services;

use App\DAO\DAOResponse\DAOResponseInterface;
use App\DAO\Filter\QueryFilter;
use App\DAO\Pagination\Pagination;
use App\DAO\ExameDAO;
use App\Entities\Exame\Exame;
use App\Mappers\ExameMapper;
use App\Services\ServiceResponse\ServiceResponse;
use App\Services\ServiceResponse\ServiceResponseInterface;
use App\Utils\Collections\QueryFilterCollection;
use App\Utils\Collections\QueryOrderCollection;
use CodeIgniter\Model;

class ExameService extends Service
{
    public function registerExame (array $data_request) : ServiceResponse {
        $exame_registration_vm = ExameMapper::getExameRegistrationVMFromArray($data_request);
        $exame_dao = new ExameDAO();
        $dao_response = $exame_dao->persistExameRegistrationVM($exame_registration_vm);
        $service_response = new ServiceResponse();
        switch ($dao_response->getStatus()) {
            case DAOResponseInterface::SUCESS:
                $data = [
                    'id_exame' => $dao_response->getData()->getId()
                ];
                $service_response->setStatus(ServiceResponseInterface::SUCESS);
                $service_response->setData($data);
                break;
            case DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS:
            case DAOResponseInterface::DUPLICATED_UNIQUE_KEY:
                $service_response->setStatus(ServiceResponseInterface::VALIDATION_PARAMS_ERROR);
                $service_response->setErrors($dao_response->getErrors());
                break;
            case DAOResponseInterface::DATABASE_CONNECTION_ERROR:
                $service_response->setStatus(ServiceResponseInterface::DATABASE_CONNECTION_ERROR);
                break;
        }
        return $service_response;
    }

    public function getExameList (?Pagination $pagination, ?QueryFilterCollection $query_filter_collection, ?QueryOrderCollection $query_order_collection) : ServiceResponse{
        $exame_dao = new ExameDAO();
        $dao_response = $exame_dao->getExameList($pagination, $query_filter_collection, $query_order_collection);
        switch ($dao_response->getStatus()) {
            case DAOResponseInterface::SUCESS:
                $service_response_status = ServiceResponseInterface::SUCESS;
                break;
            case DAOResponseInterface::RECORD_NOT_FOUND:
                $service_response_status = ServiceResponseInterface::RECORD_NOT_FOUND;
                break;
            case DAOResponseInterface::DATABASE_CONNECTION_ERROR:
                $service_response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
                break;
        }
        $service_response = ServiceResponse::builder()
            ->setStatus($service_response_status)
            ->build();
        if ($service_response_status === DAOResponseInterface::SUCESS) {
            $dao_response_data = $dao_response->getData();
            $exame_details_array = ExameMapper::getExamesDetailsArrayFromExameDetailsVMCollection($dao_response_data);
            $pagination = $dao_response->getPagination();
            $data = [
                'exames' => $exame_details_array,
                'pagination' => $pagination ? $pagination->toResponseArray() : null
            ];
            $service_response->setData($data);
        }
        return $service_response;
    }

    public function getExame (QueryFilter $query_filter) : ServiceResponse {
        $exame_dao = new ExameDAO();
        $query_filter_collection = new QueryFilterCollection();
        $query_filter_collection->push($query_filter);
        $dao_response = $exame_dao->getExame($query_filter_collection);
        $service_response_status = [
            DAOResponseInterface::SUCESS => ServiceResponseInterface::SUCESS,
            DAOResponseInterface::RECORD_NOT_FOUND => ServiceResponseInterface::RECORD_NOT_FOUND,
            DAOResponseInterface::DATABASE_CONNECTION_ERROR => ServiceResponseInterface::DATABASE_CONNECTION_ERROR,
        ][$dao_response->getStatus()];
        $service_response = ServiceResponse::builder()
            ->setStatus($service_response_status ?? ServiceResponseInterface::UNKNOWN_ERROR)
            ->build();
        if ($service_response_status === ServiceResponseInterface::SUCESS) {
            $service_response->setData($dao_response->getData()->toArray());
        }
        return $service_response;
    }

    public function deleteExame (int $id_exame) : ServiceResponse{
        $exame_dao = new ExameDAO();
        $dao_response = $exame_dao->deleteExame($id_exame);
        $service_response_status = [
            DAOResponseInterface::RESTRICT_FK_UPDATE_OR_DELETION => ServiceResponseInterface::RECORD_IS_LINKED,
            DAOResponseInterface::SUCESS => ServiceResponseInterface::SUCESS,
            DAOResponseInterface::RECORD_NOT_FOUND => ServiceResponseInterface::RECORD_NOT_FOUND,
        ][$dao_response->getStatus()];

        $service_response = ServiceResponse::builder()
            ->setStatus($service_response_status)
            ->build();
        return $service_response;
    }

    public function updateExameData (int $id_paciente, array $data) : ServiceResponse {
        $paciente_update_vm = ExameMapper::getExameUpdateVMFromArray($data);
        $paciente_dao = new ExameDAO();
        $dao_response = $paciente_dao->persistExameUpdateVM($id_paciente, $paciente_update_vm);
        $service_response = new ServiceResponse;
        $response_status = [
            DAOResponseInterface::SUCESS => ServiceResponseInterface::SUCESS,
            DAOResponseInterface::RECORD_NOT_FOUND => ServiceResponseInterface::RECORD_NOT_FOUND,
            DAOResponseInterface::DATABASE_CONNECTION_ERROR => ServiceResponseInterface::DATABASE_CONNECTION_ERROR,
            DAOResponseInterface::FOREIGN_KEY_DONT_EXISTS => ServiceResponseInterface::VALIDATION_PARAMS_ERROR,
            DAOResponseInterface::DUPLICATED_UNIQUE_KEY => ServiceResponseInterface::VALIDATION_PARAMS_ERROR,
        ][$dao_response->getStatus()];
        if (!$response_status) {
            (new LogService)->log_error($response_status, "Ocorreu um erro desconhecido durante a atualização o exame", []);
            $response_status = ServiceResponseInterface::DATABASE_CONNECTION_ERROR;
        } else if ($response_status !== ServiceResponseInterface::SUCESS) {
            $service_response->setErrors($dao_response->getErrors());
        }
        $service_response->setStatus($response_status);
        return $service_response;
    }
}