<?php
/**
 * Created by PhpStorm.
 * User: Admin
 * Date: 25.08.2020
 * Time: 23:28
 */

namespace Diamond\Controllers;


use Core\BaseController;
use Core\Concrete\RequestAwareTrait;
use Core\Contracts\RequestAwareInterface;
use Core\Helpers\Date;
use Diamond\Infrastructure\Models\Stat\Map\StatTableMap;
use Diamond\Repositories\ErrorLog\ErrorLog;
use Diamond\Repositories\ErrorLog\ErrorLogCriteria;
use Propel\Runtime\Propel;
use Symfony\Component\HttpFoundation\JsonResponse;

class StatController extends BaseController implements RequestAwareInterface
{

    use RequestAwareTrait;

    protected $errorLogRepo;

    public function __construct(ErrorLog $errorLogRepo)
    {
        $this->errorLogRepo = $errorLogRepo;
    }

    /**
     * @param int $limit
     * @return array
     * @throws \Exception
     */
    private function getDefaultDates(int $limit, int $li = 24, bool $nextDay = false): array
    {
        return \Diamond\Helpers\Date::getDefaultDates($limit, $li, $nextDay);
    }

    public function mailRequests()
    {

        $limit = (int)$this->request->query->get("interval");

        //--------------------
        $q = "
SELECT
    COUNT(m.id) as c,
    DATE_FORMAT(m.created_at,'%Y-%m-%d') as `day`
FROM _message_requests as m
WHERE
  m.created_at >= NOW() - INTERVAL ".$limit." DAY AND m.status = 'success'
  GROUP BY TO_DAYS(m.created_at)
  ";

        $con = Propel::getWriteConnection(StatTableMap::DATABASE_NAME);
        $stmt = $con->prepare($q);
        $stmt->execute();
        $dates = $this->getDefaultDates($limit);

        foreach ($stmt->fetchAll() as $row) {
            $i = strtotime($row['day']);
            if(!isset($dates[$i])){
                continue;
            }
            $dates[$i] = array(
                $i * 1000,
                (int)$row['c'],
                date(\Diamond\Helpers\Date::formatDisplay(), $i)
            );

        }

        ksort($dates);
        $dataErrors = [
            'label' => 'Отправлено успешно',

            'data' => array_values($dates)
        ];

        //---------------------------------
        $q = "
SELECT
    COUNT(m.id) as c,
    DATE_FORMAT(m.created_at,'%Y-%m-%d') as `day`
FROM _message_requests as m
WHERE
  m.created_at >= NOW() - INTERVAL ".$limit." DAY AND m.status <> 'success'
  GROUP BY TO_DAYS(m.created_at)
  ";

        $con = Propel::getWriteConnection(StatTableMap::DATABASE_NAME);
        $stmt = $con->prepare($q);
        $stmt->execute();
        $dates = $this->getDefaultDates($limit);

        foreach ($stmt->fetchAll() as $row) {
            $i = strtotime($row['day']);
            if(!isset($dates[$i])){
                continue;
            }
            $dates[$i] = array(
                $i * 1000,
                (int)$row['c'],
                date(\Diamond\Helpers\Date::formatDisplay(), $i)
            );

        }

        ksort($dates);
        $dataSuccess = [
            'label' => 'Отправлено с ошибками',
            'data' => array_values($dates)
        ];

        return new JsonResponse([
            $dataSuccess,
            $dataErrors
        ]);
    }

    /**
     * @return JsonResponse
     * @throws \Propel\Runtime\Exception\PropelException
     */
    public function performance()
    {

        $_data = $data = $_data_f = [];

        $limit = (int)$this->request->query->get("interval");
        $li = 24;

        if ($limit <= 7) {
            $li =  1;//$limit == 7 ? 4 :
            $timeSelect = 'DATE_FORMAT(_stat.datetime,"%Y-%m-%d %H:00")';
            $groupBy = "UNIX_TIMESTAMP( _stat.datetime ) DIV " . 3600 * $li;
            $where = "`datetime` >= NOW() - INTERVAL $limit DAY";

        } else {
            $timeSelect = "DATE_FORMAT(_stat.datetime,'%Y-%m-%d')";
            $groupBy = "TO_DAYS(_stat.datetime)";
            $where = "`datetime` > NOW() - INTERVAL $limit DAY AND TO_DAYS(_stat.datetime) <= TO_DAYS(NOW())";
        }

        //определеям ID
        $q1 = '
        
        SELECT *
  FROM _stat
  WHERE
  _stat.datetime >= NOW() - INTERVAL '.$limit.' DAY
LIMIT 1
  ';

        $con = Propel::getWriteConnection(StatTableMap::DATABASE_NAME);
        $stmt = $con->prepare($q1);
        $stmt->execute();

        $res = $stmt->fetch();

        $minId = $res['id']??1 ;

        $q = "
SELECT
  _stat.id,
  MAX(_stat.elapsed_time) as c,
  $timeSelect AS t
FROM _stat
WHERE 
  `id` >= $minId AND _stat.elapsed_time > 0
  GROUP BY $groupBy
  ";

        $con = Propel::getWriteConnection(StatTableMap::DATABASE_NAME);
        $stmt = $con->prepare($q);
        $stmt->execute();

        $dates = $this->getDefaultDates($limit,$li);



        foreach ($stmt->fetchAll() as $row) {
            //если идет число не в часах
            $i = strtotime($row['t']);

            if(!isset($dates[$i])){
                continue;
            }

            $dates[$i] = array(
                $i * 1000,
                (int)$row['c'],
                date(\Diamond\Helpers\Date::formatDisplay(), $i)
            );
        }

        $lastIndex = strtotime((new \DateTime())->format('Y-m-d'));

        unset($dates[$lastIndex]);

        ksort($dates);




        $_data_f [] = array(
            'label' => 'Время выполнения, cек.',
            'data' =>  array_values($dates)
        );

        //------------------------------
        $q = "

SELECT
  _stat.id,
  MAX(_stat.memory) AS c,
   $timeSelect AS t
FROM _stat
WHERE
  `id` >= $minId AND _stat.memory > 0

  GROUP BY $groupBy
  ";

        $stmt = $con->prepare($q);
        $stmt->execute();

        $dates = $this->getDefaultDates($limit, $li);

        foreach ($stmt->fetchAll() as $row) {

            $i = strtotime($row['t']);

            if(!isset($dates[$i])){
                continue;
            }

            $dates[$i] = array(
                $i * 1000,
                round((int)$row['c'] / 1024 / 1024),
                date(\Diamond\Helpers\Date::formatDisplay(), $i)
            );
        }

        unset($dates[$lastIndex]);

        ksort($dates);

        $_data_f [] = array(
            'label' => 'Память,Мб',
            'data' => array_values($dates)
        );

        return new JsonResponse($_data_f);
    }


    /**
     * @return JsonResponse
     * @throws \Propel\Runtime\Exception\PropelException
     */
    public function requests():JsonResponse
    {

        $_data_f = [];
        $li = 24;
        $limit = (int)$this->request->query->get('interval');
        if ($limit <= 7) {
            $li = 1;
            $timeSelect = 'DATE_FORMAT(_stat.datetime,"%Y-%m-%d %H:00")';
            $groupBy = 'UNIX_TIMESTAMP( _stat.datetime ) DIV ' . 3600 * $li;
            $timeSelect2 = 'd';
            $where = "`datetime` >= NOW() - INTERVAL $limit DAY";


        } else {
            $groupBy = "TO_DAYS(_stat.datetime)";
            $timeSelect = "DATE_FORMAT(_stat.datetime,'%Y-%m-%d')";
            $timeSelect2 = "DATE_FORMAT(s.datetime,'%Y-%m-%d')";
            $where = "`datetime` > NOW() - INTERVAL $limit DAY AND TO_DAYS(_stat.datetime) <= TO_DAYS(NOW())";
        }


        //определеям ID
        $q1 = '
        
        SELECT *
  FROM _stat
  WHERE
  _stat.datetime >= NOW() - INTERVAL '.$limit.' DAY
LIMIT 1
  ';

        $con = Propel::getWriteConnection(StatTableMap::DATABASE_NAME);
        $stmt = $con->prepare($q1);
        $stmt->execute();

        $res = $stmt->fetch();

        $minId = $res['id']??1 ;




        $q = "
SELECT 
  COUNT(remote_addr) AS c,
  $timeSelect2 AS t
  FROM(
SELECT
  _stat.id,
  _stat.remote_addr,
  _stat.datetime,
  $timeSelect AS d
  
FROM _stat

WHERE 
  `id` >= $minId

AND client_type <> 'robot'

  GROUP BY remote_addr, $groupBy
) s
 
GROUP BY s.d

  ";

        $con = Propel::getWriteConnection(StatTableMap::DATABASE_NAME);
        $stmt = $con->prepare($q);
        $stmt->execute();


        $dates = $this->getDefaultDates($limit, $li);

        foreach ($stmt->fetchAll() as $row) {
            $i = strtotime($row['t']);
            $dates[$i] = array(
                $i * 1000,
                (int)$row['c'],
                date(\Diamond\Helpers\Date::formatDisplay(), $i)
            );

        }

        $lastIndex = strtotime((new \DateTime())->format('Y-m-d'));

        unset($dates[$lastIndex]);

        ksort($dates);



        $_data_f [] = array(
            'label' => 'Пользователи',
            'data' => array_values($dates)
        );


        //------------------------------
        $q = "
SELECT 
  COUNT(remote_addr) AS c,
  $timeSelect2 AS t
  FROM(
SELECT
  _stat.id,
  _stat.remote_addr,
  _stat.datetime,
  $timeSelect AS d
  
FROM _stat

WHERE 
  `id` >= $minId

AND client_type = 'robot'
  GROUP BY remote_addr, $groupBy
) s
 
GROUP BY s.d

  ";

        $stmt = $con->prepare($q);
        $stmt->execute();

        $dates = $this->getDefaultDates($limit, $li);
        foreach ($stmt->fetchAll() as $row) {
            $i = strtotime($row['t']);
            $dates[$i] = array(
                $i * 1000,
                (int)$row['c'],
                date(Date::formatDisplay(), $i)
            );

        }

        unset($dates[$lastIndex]);

        ksort($dates);


        $_data_f [] = array(
            'label' => 'Боты',
            'data' => array_values($dates)
        );

        return new JsonResponse($_data_f);
    }


    /**
     * @return JsonResponse
     * @throws \Repo\Concrete\Exceptions\Collection
     */
    public function errors(): JsonResponse
    {

        $limit = (int)$this->request->query->get('interval');

        $errors = $this->errorLogRepo->findByCriteria(
            ErrorLogCriteria::create()
        );

        $dates = $this->getDefaultDates($limit,24,true);

        foreach ($errors as $error) {

            $i = date_create(date('Y-m-d', $error->getDate()->getTimestamp()))->getTimestamp();

            if(!isset($dates[$i])){
                continue;
            }

            /**
             * @var ErrorLogEntity $error
             */
            $dates[$i] = [
                $i * 1000,
                $error->getErrors(),
                sprintf('%s - %s errors',date('Y-m-d', $error->getDate()->getTimestamp()), $error->getErrors())
            ];

        }

        $_data_f [] = array(
            'label' => 'Системные ошибки',
            'data' => array_values($dates)
        );
        return new JsonResponse(array_values($dates));
    }

}