<?php

declare(strict_types=1);

final class FingerprintPostController extends AbstractController
{
    protected string $route = '/api/v1/fingerprint';
    protected array $mandatoryAttributes = [
        'fingerprint',
        'userId',
    ];

    public function __construct(string $url)
    {
        parent::__construct($url);

        $this->response = new ApiJsonResponse();
    }

    public function handle(): void
    {
        parent::handle();

        $db = new MySqlDatabase();
        $json = json_decode($this->requestBody);
        $fingerprint = new Fingerprint(null, $db);

        try {
            $fingerprint->setFingerprint($json->fingerprint);
            $fingerprint->setUserId($json->userId);

            if (!$db->hasTransaction()) {
                $db->startTransaction();
            }

            $fingerprint->Save();

            $qrCode = new QrCode($fingerprint->getFingerprintId(), $fingerprint->getFingerprint());
            $qrCode->generate();
            $qrCode->save();

            $db->commit();

            $this->response->setParameter('fingerprintId', $fingerprint->getFingerprintId());
        } catch (QrCodeException $e) {
            $db->rollback();

            $this->response->setParameter('success', false);
            $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
            $this->response->setMessage('An error occured during qr code creation!');
        } catch (Throwable $e) {
            $db->rollback();
            $this->catchDatabaseException($e->getMessage(), $json);
        }
    }

    private function catchDatabaseException(string $message, object $json): void
    {
        $this->response->setParameter('success', false);

        if (substr_count($message, 'foreign key constraint fails') > 0) {
            $this->response->setMessage(sprintf('User with id %d doesn\'t exist!', $json->userId));
            $this->response->setStatus(ServerStatus::NOT_FOUND);
        } elseif (substr_count($message, 'Duplicate entry') > 0) {
            $this->response->setMessage(sprintf('Fingerprint %s already exists!', $json->fingerprint));
            $this->response->setStatus(ServerStatus::BAD_REQUEST);
        } else {
            $this->response->setMessage($message);
            $this->response->setStatus(ServerStatus::INTERNAL_ERROR);
        }
    }
}