<?php
/**
 * Copyright (c) 2016 Serhii Borodai <clarifying@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 *
 */

/**
 *  http api
 * 
 *  1. summary report
 *  2. 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 */

namespace App\Action;

use App\Authentication\UserService;
use App\Authentication\AggregateAuth;
use App\Model\Users;
use App\Model\Sites;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\HtmlResponse;
use Zend\Diactoros\Response\JsonResponse;

/**
 * Class Statistics
 * @package App\Action
 */
class Statistics extends Common
{
    const ACTION_SUMMARY_REPORT = 'summary';
    const ACTION_LINECHART_REPORT = 'linechart';
    const ACTION_SUBDOMAINS_LIST = 'subdomains';
    const ACTION_SITESSTAT_REPORT = 'sitesstat';
    const ACTION_REPORT_LIST = ['minstat', 'bidstat', 'pagestat', 'blockstat', 'winstat', 'ndspstat', 'providersblockstat'];
    const ACTION_GEO_LIST = 'geolist';
    const ACTION_SITES_LIST = 'siteslist';
    const ACTION_ZONES_LIST = 'zoneslist';
    const ACTION_CODESTAT_GLOBAL_REPORT = 'codestatglobal';
    const ACTION_CODESTAT_REPORT = 'codestat';
    
    

    /**
     * @param ServerRequestInterface $request
     * @param ResponseInterface $response
     * @param callable|null $next
     * @return HtmlResponse
     */
    function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
    {
        
        /** @var Sites $sitesModel */
        $sitesModel = $this->container->get(Sites::class);        
        
        /** @var UserService $auth */
        $auth = $this->container->get(UserService::class);
        
        /** @var AggregateAuth $aggregateAuth */
        $aggregateAuth = $this->container->get(AggregateAuth::class);
        
        /** @var Statistics $stats */
        $stats = $this->container->get(\App\Model\Statistics::class);
        
        /** @var Users $usersModel */
        $usersModel = $this->container->get(Users::class);
        
        //$isAdmin = ($aggregateAuth->getIdentity()->getRoleId() == 'admin');
        $isAdmin = in_array($aggregateAuth->getIdentity()->getRoleId(), ['admin','marker']);
        $isManager = ($aggregateAuth->getIdentity()->getRoleId() == 'manager');
        
        $params = $request->getParsedBody();

        
        if ((!$isAdmin && !$isManager) || $params['userid']) { // Список сайтов пользователей
            $userId = ($params['userid']) ? $params['userid'] : $auth->getIdentity()->getId();
            $user = $usersModel->findById($userId);
            $currency = $user->getCurrencyCode();
            
            $listSites = $sitesModel->findByUserId($userId)->buffer();
            
            $listDomains = array();
            foreach($listSites as $site) {
                $listDomains[] = $site->getDomain();
                // Добавляем в список алиасы:
                if ($site->getAlias()) {
                    $site_aliases = explode(",", $site->getAlias());
                    foreach ($site_aliases as $site_alias) {
                        if ($site_alias != $site->getDomain()) {
                            $listDomains[] = $site_alias;
                        }
                    }
                }
            }
            
            // Добавлям домены доступных сайтов
            /** @var \App\Model\AccessUsersSites $accessUsersSitesModel */            
            $accessUsersSitesModel = $this->container->get(\App\Model\AccessUsersSites::class);
            $listAccessSites = $accessUsersSitesModel->findSitesByUserId($userId);
            
            foreach($listAccessSites as $site) {
                $listDomains[] = $site->getDomain();
            }
            
        } else if ($isManager) { // Список сайтов менеджера
            $currency = (isset($_COOKIE["adminCurrency"])) ? $_COOKIE["adminCurrency"] : 'USD';
            
            $manager_id = $aggregateAuth->getIdentity()->getId();
            $manager_users = $usersModel->findBySupportId($manager_id);
            $managerSites = $sitesModel->findByUserId($manager_users)->buffer();
            
            $listDomains = array();
            foreach($managerSites as $site) {
                if (!in_array($site->getDomain(), $listDomains)) {
                    $listDomains[] = $site->getDomain();
                }
            }

        /*    
        } else if ($params['managerid']) { // Список сайтов менеджера
            $currency = (isset($_COOKIE["adminCurrency"])) ? $_COOKIE["adminCurrency"] : 'USD';
            
            $listUsersId = $usersModel->findBySupportId($params['managerid']);
            
            $listDomains = array();
            $managerSites = $sitesModel->findByUserId($listUsersId)->buffer();
            foreach($managerSites as $site) {
                if (!in_array($site->getDomain(), $listDomains)) {
                    $listDomains[] = $site->getDomain();
                }
            }
        */
        } else { // Список сайтов админа
            $currency = (isset($_COOKIE["adminCurrency"])) ? $_COOKIE["adminCurrency"] : 'USD';
            
            $listDomains = array();
            $adminSites = $sitesModel->findAllSites();
            foreach($adminSites as $site) {
                $listDomains[] = $site;
            }
            
        }
        
        
        
        $month = trim($params['month']);
        if(!preg_match('/^\d{4,4}-\d{2,2}$/', $month)) {
            $month = '';
        }
        
        $sites = trim($params['domains']);
        if(!$sites) {
            $sites = array();
        } else {
            $sites = array_filter(array_map('trim', explode(',', $sites)));
        }    
        
        foreach($sites as $i => $requestSite) {
            $is_valid = false;
            foreach($listDomains as $validDomain) {
                if(preg_match('/'.$validDomain.'$/', $requestSite)) {
                    $is_valid = true;
                    break;
                }
            }            
            if(!$is_valid) {
                unset($sites[$i]);
            }
        }
        
        $subdomains = trim($params['subdomains']);
        $subdomains = ($subdomains == 1) ? true : false;
        
        $domain = trim($params['domain']);
        $domains = array($domain);
        
        $allStat = (($isAdmin || $isManager) && !$params['userid']);
        $group = ($isAdmin && isset($params['group']) && !$params['userid'] && !$params['managerid']) ? trim($params['group']): "false";
        
        $action = $params['action'];
        $metrics_types = $this->container->get('config')['metrics'];        
        $dates = $params['dates'];
        $geo = ($params['geo'] !='') ? $params['geo'] : null;
        $sites_id = ($params['sites_id'] !='') ? $params['sites_id'] : null;
        $zones_id = ($params['zones_id'] !='') ? $params['zones_id'] : null;
        
        // Формируем список id сайтов для codestat: 
        $sites_id_code = ($params['sites'] !='') ? $params['sites'] : null;
        if (!is_null($sites_id_code)) {
            $sites_id_code = array_map(function($id){return (int)$id;}, $sites_id_code);
        }
        $codes = $params['codes'];
        
        // Формируем фильтры:
        if (!is_null($sites_id)) {
            $sites_id['list'] = array_map(function($id){return (int)$id;}, $sites_id['list']);
        }
        if (!is_null($zones_id)) {
            $zones_id['list'] = array_map(function($id){return (int)$id;}, $zones_id['list']);
        }
        
        
        if($params['action'] == self::ACTION_SUMMARY_REPORT) {
            $data = $stats->getSummuryReport($sites, $currency, $subdomains, $allStat, $group);
        } elseif($params['action'] == self::ACTION_LINECHART_REPORT) {
            list($data) = $stats->getPeriodReport($month, $sites, $currency, $subdomains, $allStat, $group);
        } elseif($params['action'] == self::ACTION_SITESSTAT_REPORT) {
            $data = $stats->getSitesReport($month, $sites, $currency, $subdomains, $allStat, $group);
        } elseif($params['action'] == self::ACTION_SUBDOMAINS_LIST) {
            $data = $stats->getSubDomains($domains);
        } elseif(in_array($params['action'], self::ACTION_REPORT_LIST)) {
            $type = $metrics_types[$action]['type'];
            $fields = $metrics_types[$action]['fields'];
            if (!in_array('ZoneID', $metrics_types[$action]['filters'])) {
                $zones_id = null;
            }
            $data = $stats->getStatReport($action, $type, $fields, $dates, $geo, $sites_id, $zones_id, $params['by_sites'], $params['by_zones'], $params['by_countries']);
        } elseif($params['action'] == self::ACTION_GEO_LIST) {
            $metric = $params['metric'];
            $type = $metrics_types[$metric]['type'];
            $fields = $metrics_types[$metric]['fields'];
            $data = $this->getGeoList($type, $fields);
        } elseif($params['action'] == self::ACTION_SITES_LIST) {
            $data = $this->getSitesList();
        } elseif($params['action'] == self::ACTION_ZONES_LIST) {
            $data = $this->getZonesList();
        } elseif($params['action'] == self::ACTION_CODESTAT_GLOBAL_REPORT) {
            $data = $stats->getCodestatGlobalReport($sites_id_code, $codes);
        } elseif($params['action'] == self::ACTION_CODESTAT_REPORT) {
            list($data) = $stats->getCodestatReport($month, $sites_id_code, $codes);
        }
        
        return new JsonResponse($data);
    }
    
    private function getGeoList($type, $fields)
    {
        /** @var \App\Model\Statistics $stats */
        $stats = $this->container->get(\App\Model\Statistics::class);
        
        // Определяем список наиболее популярных стран:
        //$geo_popular = $stats->getStatReportCountries($type, $fields);
        if ($geo_popular) {
            $list_codes = $this->container->get('config')['country_codes'];
            foreach (array_keys($geo_popular) as $code) {
                $geo_popular[$code] = $list_codes[$code];
            }
        } else {
            $geo_popular = $this->container->get('config')['site_countries'];
        }
        
        return $geo_popular;
    }
    
    private function getSitesList()
    {
        /** @var \App\Model\Sites $sitesModel */            
        $sitesModel = $this->container->get(\App\Model\Sites::class);
        $sites = array();
        foreach($sitesModel->findAll(null, 'domain ASC') as $site) {
            $sites[] = array(
                'id' => $site->getId(),
                'domain' => $site->getDomain(),
            );
        }
        
        return $sites;
    }
    
    private function getZonesList()
    {
        /** @var \App\Model\Sites $sitesModel */            
        $sitesModel = $this->container->get(\App\Model\Sites::class);
        
        /** @var \App\Model\Sites $zonesModel */            
        $zonesModel = $this->container->get(\App\Model\Zones::class);

        $zones = array();
        foreach($zonesModel->findAll($where ?: null, 'id ASC') as $zone) {
            $site = $sitesModel->findOne(['id' => $zone->getSiteId()]);
            $site_domain = $site->getDomain();
            $zones[$zone->getId()] = array(
                'domain' => $site_domain,
                'site_id' => $zone->getSiteId(),
                'size' => $zone->getWidth().'x'.$zone->getHeight(),
            );
        }

        return $zones;
    }
}