<?php

namespace Axioma\Server;

trait AppDB
{
    private function openDatabase(&$error = null)
    {
        if (!$this->checkDatabasePath($error)) {
            return null;
        }
        try {
            $pdo = new \PDO('sqlite:' . $this->databasePath());
            $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
            $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
            return $pdo;
        } catch (\PDOException $e) {
            $error = $e->getMessage();
            return null;
        }
    }

    private function closeDatabase(&$pdo, &$error = null)
    {
        $pdo = null;
    }

    public function getActiveUsers(&$error = null)
    {
        if ($pdo = $this->openDatabase($error)) {
            $query = 'select clients.username, clients.ip, clients.public_ip, clients.sid, clients.version, ' .
                     'licenses.acquired,licenses.expire ' .
                     'from licenses join clients on licenses.uid=clients.id where licenses.active=1';
            try {
                $stmt = $pdo->prepare($query);
                if ($stmt === false) {
                    $error = _('Неизвестная ошибка базы данных');
                    return null;
                }
                if ($stmt->execute() === false) {
                    $error = _('Неизвестная ошибка базы данных');
                    return null;
                }
                $users = $stmt->fetchAll(\PDO::FETCH_ASSOC);
                if ($users === false) {
                    $error = _('Неизвестная ошибка базы данных');
                    return null;
                }
                foreach ($users as &$user) {
                    if ($user['ip'] != $user['public_ip']) {
                        $user['ip'] = $user['public_ip'] . ' (' . $user['ip'] . ')';
                    }
                    $user['version'] = implode('.', array_slice(unpack('C*', pack('N', $user['version'])), 1, 3));
                    $user['acquired'] = (new \DateTime())->setTimestamp($user['acquired']);
                    $user['expire'] = (new \DateTime())->setTimestamp($user['expire']);
                }
                $this->closeDatabase($pdo, $error);
                return $users;
            } catch (\PDOException $e) {
                $error = $e->getMessage();
                return null;
            }
        }
        return null;
    }

    public function getLicenseHistory(&$error = null)
    {
        if ($pdo = $this->openDatabase($error)) {
            // TODO: можно переписать в одно обращение к licenses, используя With
            $query = 'select clients.username, clients.ip, clients.public_ip, clients.sid, clients.version, ' .
                'l.active, l.acquired, ' .
                'case when l.active = 1 then l.expire else null end as expire, ' .
                'l2.released, (l2.released - l.acquired) as duration ' .
                'from licenses l join clients join (' .
                'select id, case when (released is not null or active = 1) then released else expire end ' .
                'as released from licenses' .
                ') l2 on l.uid=clients.id and l.id=l2.id';
            try {
                $stmt = $pdo->prepare($query);
                if ($stmt === false) {
                    $error = _('Неизвестная ошибка базы данных');
                    return null;
                }
                if ($stmt->execute() === false) {
                    $error = _('Неизвестная ошибка базы данных');
                    return null;
                }
                $licenses = $stmt->fetchAll(\PDO::FETCH_ASSOC);
                if ($licenses === false) {
                    $error = _('Неизвестная ошибка базы данных');
                    return null;
                }
                foreach ($licenses as &$user) {
                    if ($user['ip'] != $user['public_ip']) {
                        $user['ip'] = $user['public_ip'] . ' (' . $user['ip'] . ')';
                    }
                    $user['active'] = $user['active'] == 1;
                    $user['version'] = implode('.', array_slice(unpack('C*', pack('N', $user['version'])), 1, 3));
                    if (empty($user['released']) && !$user['active']) {
                        $user['released'] = $user['expire'];
                    }
                    $user['expire'] = $user['active'] ? $user['expire'] : '';
                }
                $this->closeDatabase($pdo, $error);
                return $licenses;
            } catch (\PDOException $e) {
                $error = $e->getMessage();
                return null;
            }
        }
        return null;
    }
}
