<?php

/**
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */
namespace Piwik\Plugins\UserId\RecordBuilders;

use Piwik\ArchiveProcessor;
use Piwik\ArchiveProcessor\Record;
use Piwik\ArchiveProcessor\RecordBuilder;
use Piwik\Config;
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Plugins\UserId\Archiver;
use Piwik\RankingQuery;
class Users extends RecordBuilder
{
    public function __construct()
    {
        parent::__construct();
        $this->maxRowsInTable = Config::getInstance()->General['datatable_archiving_maximum_rows_userid_users'];
        $this->columnToSortByBeforeTruncation = Metrics::INDEX_NB_VISITS;
    }
    public function getRecordMetadata(ArchiveProcessor $archiveProcessor) : array
    {
        return [Record::make(Record::TYPE_BLOB, Archiver::USERID_ARCHIVE_RECORD)];
    }
    protected function aggregate(ArchiveProcessor $archiveProcessor) : array
    {
        $record = new DataTable();
        $visitorIdsUserIdsMap = [];
        $userIdFieldName = Archiver::USER_ID_FIELD;
        $visitorIdFieldName = Archiver::VISITOR_ID_FIELD;
        $rankingQueryLimit = $this->getRankingQueryLimit();
        $rankingQuery = \false;
        if ($rankingQueryLimit > 0) {
            $rankingQuery = new RankingQuery($rankingQueryLimit);
            $rankingQuery->addLabelColumn($userIdFieldName);
            $rankingQuery->addLabelColumn($visitorIdFieldName);
        }
        /** @var \Zend_Db_Statement $query */
        $query = $archiveProcessor->getLogAggregator()->queryVisitsByDimension(array($userIdFieldName), "log_visit.{$userIdFieldName} IS NOT NULL AND log_visit.{$userIdFieldName} != ''", array("LOWER(HEX({$visitorIdFieldName})) as {$visitorIdFieldName}"), \false, $rankingQuery, $userIdFieldName . ' ASC');
        $rowsCount = 0;
        foreach ($query as $row) {
            $rowsCount++;
            $columns = [Metrics::INDEX_NB_UNIQ_VISITORS => $row[Metrics::INDEX_NB_UNIQ_VISITORS], Metrics::INDEX_NB_VISITS => $row[Metrics::INDEX_NB_VISITS], Metrics::INDEX_NB_ACTIONS => $row[Metrics::INDEX_NB_ACTIONS], Metrics::INDEX_NB_USERS => $row[Metrics::INDEX_NB_USERS], Metrics::INDEX_MAX_ACTIONS => $row[Metrics::INDEX_MAX_ACTIONS], Metrics::INDEX_SUM_VISIT_LENGTH => $row[Metrics::INDEX_SUM_VISIT_LENGTH], Metrics::INDEX_BOUNCE_COUNT => $row[Metrics::INDEX_BOUNCE_COUNT], Metrics::INDEX_NB_VISITS_CONVERTED => $row[Metrics::INDEX_NB_VISITS_CONVERTED]];
            $record->sumRowWithLabel($row[$userIdFieldName], $columns);
            // Remember visitor ID per user. We use it to fill metadata before actual inserting rows to DB.
            if (!empty($row[Archiver::USER_ID_FIELD]) && !empty($row[Archiver::VISITOR_ID_FIELD])) {
                $visitorIdsUserIdsMap[$row[Archiver::USER_ID_FIELD]] = $row[Archiver::VISITOR_ID_FIELD];
            }
        }
        $this->setVisitorIds($record, $visitorIdsUserIdsMap);
        return [Archiver::USERID_ARCHIVE_RECORD => $record];
    }
    /**
     * Fill visitor ID as metadata before actual inserting rows to DB.
     *
     */
    private function setVisitorIds(DataTable $dataTable, array $visitorIdsUserIdsMap)
    {
        foreach ($dataTable->getRows() as $row) {
            $userId = $row->getColumn('label');
            if (isset($visitorIdsUserIdsMap[$userId])) {
                $row->setMetadata(Archiver::VISITOR_ID_FIELD, $visitorIdsUserIdsMap[$userId]);
            }
        }
    }
    private function getRankingQueryLimit()
    {
        $configGeneral = Config::getInstance()->General;
        $configLimit = $configGeneral['archiving_ranking_query_row_limit'];
        $limit = $configLimit == 0 ? 0 : max($configLimit, $this->maxRowsInTable);
        return $limit;
    }
}
