<?php
/**
 * @author      Alex Bilbie <hello@alexbilbie.com>
 * @copyright   Copyright (c) Alex Bilbie
 * @license     http://mit-license.org/
 *
 * @link        https://github.com/thephpleague/oauth2-server
 */

namespace Docuform\Api\Authentication\Repositories;

use DI\DependencyException;
use DI\NotFoundException;
use Docuform\Api\Exception\ApiHttpException;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
use Docuform\Api\Authentication\Entities\AuthCodeEntity;
use DI\Container;
use Docuform\Database\DbPDO;

global $g_authCodeTTLSec;

$g_authCodeTTLSec = 1*60;

class AuthCodeRepository implements AuthCodeRepositoryInterface
{
  /* @var Container $m_container */
  private Container $m_container;

  /**
   * ApiClientRepository constructor.
   *
   * @param $container
   *
   * @throws ApiHttpException
   */
  public function __construct($container)
  {
    $this->m_container = $container;
  }

  /**
   * {@inheritdoc}
   */
  public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): void
  {
    // Some logic to persist the auth code to a database

    try
    {
      /** @var DbPDO $db */
      $db = $this->m_container->get('sqliteDb');

      if ($db != null)
      {
        $insert = "INSERT INTO AUTHCODES (code, created) VALUES (:code, :created)";
        $stmt = $db->prepare($insert);

        $authCode = $authCodeEntity->getIdentifier();
        $time = time();

        $stmt->bindParam(':code', $authCode);
        $stmt->bindParam(':created', $time);

        $stmt->execute();
      }
    }
    catch (DependencyException|NotFoundException $e)
    {
    }
  }

  /**
   * @param string $codeId
   * @return void
   */
  public function revokeAuthCode(string $codeId): void
  {
    // Some logic to revoke the auth code in a database

    /** @var DbPDO $db */
    try
    {
      $db = $this->m_container->get('sqliteDb');

      if ($db != null)
      {
        $delStmt = "DELETE FROM AUTHCODES WHERE code=:code";
        $stmt = $db->prepare($delStmt);

        $stmt->bindParam(':code', $codeId);

        $stmt->execute();
      }
    }
    catch (DependencyException|NotFoundException $e)
    {
    }
  }

  /**
   * @param string $codeId
   * @return bool
   */
  public function isAuthCodeRevoked(string $codeId): bool
  {
    global $g_authCodeTTLSec;

    $bRevoked = true;

    /** @var DbPDO $db */
    try
    {
      $db = $this->m_container->get('sqliteDb');

      if ($db != null)
      {
        $sql = "DELETE FROM AUTHCODES WHERE created<:created";
        $stmt = $db->prepare($sql);

        $created = time() - $g_authCodeTTLSec;

        $stmt->bindValue(':created', $created);

        $stmt->execute();

        $sql = "SELECT id FROM AUTHCODES WHERE code=:code";
        $stmt = $db->prepare($sql);

        $stmt->bindValue(':code', $codeId);

        $stmt->execute();

        $res = $stmt->fetch();

        if (isset($res['id']))
        {
          $bRevoked = false;
        }
      }
    }
    catch (DependencyException|NotFoundException $e)
    {
    }

    return $bRevoked;
  }

  /**
   * @return AuthCodeEntityInterface|AuthCodeEntity
   */
  public function getNewAuthCode(): AuthCodeEntityInterface|AuthCodeEntity
  {
    return new AuthCodeEntity();
  }
}