<?php

/**
 * Class CFHostCount
 */
class CFHostCount
{
    private $from;
    private $to;
    private $period;

    /**
     * @var Pest
     */
    private $restClient;

    public const DEFAULT_PERIOD = 'week';

    /**
     * @var array
     */
    public static $periodsMap = [
        'day' => ['postgresFormat' => 'dd Mon yyyy', 'phpFormat' => 'd M Y'],
        'week' => ['postgresFormat' => '"Week #"WW yyyy', 'phpFormat' => '\W\e\e\k #W Y'],
        'month' => ['postgresFormat' => 'Mon yyyy', 'phpFormat' => 'M Y'],
        'year' => ['postgresFormat' => 'yyyy', 'phpFormat' => 'Y'],
    ];

    public function __construct($from, $to, $period = DEFAULT_PERIOD)
    {
        $this->from = $from;
        $this->to = $to;
        $this->period = strtolower($period);
    }

    /**
     * @return array
     */
    public function getCountByPeriod()
    {


        $jsonPayload = json_encode(array(
            'query' => vsprintf('SELECT COUNT(*) as host_count, to_char(firstreporttimestamp , \'%s\' ) as period  FROM hosts WHERE firstreporttimestamp BETWEEN \'%s\'::timestamp AND \'%s\'::timestamp GROUP BY period', [
                self::$periodsMap[$this->period]['postgresFormat'], $this->from, $this->to
            ]),
        ));
        $period = $this->combinePeriods($this->getQueryResult($jsonPayload));

        return ['period' => $this->period, 'data' => $this->decorateResponse($period)];
    }

    private function decorateResponse($periods)
    {
        $data = [];
        foreach ($periods as $date => $count) {
            $data[] = ['date' => $date, 'count' => $count];
        }
        return $data;
    }

    private function combinePeriods($periodWithData)
    {
        $defaultPeriods = $this->preparePeriod();
        foreach ($periodWithData as $date => $count) {
            $defaultPeriods[$date] = $count;
        }
        return $defaultPeriods;
    }

    private function preparePeriod()
    {

        $period = new DatePeriod(
            new DateTime($this->from),
            new DateInterval('P1D'),
            new DateTime($this->to)
        );
        $periods = [];
        foreach ($period as $date) {
            $periods[$date->format(self::$periodsMap[$this->period]['phpFormat'])] = 0;
        }
        return $periods;
    }


    /**
     * @param $jsonPayload
     * @return array
     */
    private function getQueryResult($jsonPayload)
    {
        $requestHeaders = getallheaders();
        $headers = ['Authorization: ' . $requestHeaders['Authorization']];
        $jsonBody = json_decode($this->restClient->post('/query/', $jsonPayload, $headers));

        $data = [];
        foreach ($jsonBody->data[0]->rows as $item) {
            $data[$item[1]] = (int)$item[0];
        }
        return $data;
    }

    /**
     * @param $restClient
     */
    public function setRestClient($restClient)
    {
        $this->restClient = $restClient;
    }
}

class UnfilteredHostCountModel
{
    /**
     * @var PDO
     */
    private $pdo;

    private $queries = [
        'hostCount' => 'SELECT COUNT(*) as count 
                        FROM __hosts 
                        WHERE deleted IS NULL',
        'licensedHostCount' => 'SELECT COUNT(*) as count 
                                FROM __hosts 
                                WHERE deleted IS NULL AND lastreporttimestamp IS NOT NULL',
        'deletedHostCount' => 'SELECT COUNT(*) as count 
                               FROM __hosts 
                               WHERE deleted IS NOT NULL'
    ];

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function getResult()
    {
        $result = [];

        foreach ($this->queries as $name => $query) {
            $result[$name] = $this->getCountByQuery($query);
        }

        return $result;
    }

    private function getCountByQuery($query)
    {
        $result = $this->pdo->query($query)->fetch(PDO::FETCH_ASSOC);
        return $result['count'];
    }
}
