<?php

namespace Signteer\Core\Finder;

use Plainwork\Database\Database;
use Plainwork\Database\Query;
use Plainwork\DateTime\TimeFactory;
use Signteer\Core\Criteria\EventLogCriteria;
use Signteer\Core\Criteria\CommonLimitCriteria;
use Signteer\Core\Database\EventLogTable as Table;
use Signteer\Core\Event\EventEnvelope;
use Signteer\Core\Event\EventBus;

class EventLogFinder
{
    public $db = Database::class;
    public $table = Table::class;
    public $timeFactory = TimeFactory::class;
    public $eventBus = EventBus::class;

    public function count(EventLogCriteria $c): int
    {
        $q = $this->table->applyCriteria(new Query(), $c);

        $q = $q->select('COUNT(' . Table::COL_ID . ')', Table::NAME);
        $res = $this->db->select($q);
        $ret = $res ? current(current($res)) : 0;

        return $ret;
    }

    public function find(EventLogCriteria $c, int $limit = 0, int $offset = 0): array
    {
        $ret = [];

        $q = $this->table->applyCriteria((new Query()), $c);

        $q = $q
            ->select(Table::COL_ID, Table::NAME)
            ->select(Table::COL_EVENT_NAME, Table::NAME)
            ->select(Table::COL_EVENT_DATA, Table::NAME)
            ->select(Table::COL_WHEN, Table::NAME)
            ->select(Table::COL_USER_ID, Table::NAME)
            ->orderDesc(Table::COL_ID)
            ->limit($limit)
            ->offset($offset)
        ;

        $rows = $this->db->select($q);
        foreach ($rows as $r) {
            $alias = $r[Table::COL_EVENT_NAME];
            $data = json_decode($r[Table::COL_EVENT_DATA], true);

            $event = $this->eventBus->reconstruct($alias, $data) ?? $alias;
            $when = $this->timeFactory->fromString($r[Table::COL_WHEN]);
            $user = $r[Table::COL_USER_ID];

            $m = new EventEnvelope($r[Table::COL_ID], $event, $user, $when);
            $ret[$m->getId()] = $m;
        }

        return $ret;
    }
}
