<?php

namespace App\Model;

use App\Model\Sites;
use App\Model\Zones;

class Statistics 
{   
    private $hashSolt = '';
    
    public function __construct(Sites $sites, Zones $zones, $countries) 
    {
        $this->hashSolt = 'FsRpCKc021PzwqOR8o1mXLe8AIS6YmnfkDvECBY6MzGWHhceS4EvdOnW7dYHt7AA';
        
        $this->sitesModel = $sites;
        $this->zonesModel = $zones;
        $this->countryCodes = $countries;
    }

    // Список поддоменов
    public function getSubdomains(array $sites)
    {
        if(!$sites) {
            return array();
        }              
        
        $res = $this->apiRequest(array(
            'method' => 'subdomains',
            'data' => array(
                'domains' => $sites
            )            
        ));
        
        $allSubdomains = array();
        foreach($res as $domain => $subDomains) {
            $allSubdomains = array_merge($allSubdomains, $subDomains);            
        }
        
        sort($allSubdomains);
        
        return $allSubdomains;
    }
    
    // Сводная таблица (над графиком)
    public function getSummuryReport(array $sites, $currency, $subdomains, $allStat, $group)
    {
        if(!count($sites) && ($group != 'all')) {
            return array();
        }                
            
        $dataRequest = array(
            'method' => 'global_stat',
            'data' => array(
                'subdomains' => $subdomains,
                'currency' => $currency,
            )            
        );
        
        if ($allStat) {
            $dataRequest['data']['all_stat'] = true;
        }
        
        if ($group == 'all') {
            $dataRequest['data']['group'] = 'all';
        } else {
            $dataRequest['data']['domains'] = $sites;
        }
        
        /*
        $dataRequest = array(
            'method' => 'global_stat',
            'data' => array(
                'subdomains' => false,
                'currency' => "USD",
                'domains' => ["ua.sinoptik.ua"]
            )
        );
        $summaryReport = $this->apiRequest($dataRequest);
        return $summaryReport;
        */
        
        $summaryReport = $this->apiRequest($dataRequest);
        $summaryReport = $summaryReport['stat'] ?: array();

        return $summaryReport;
    }
    
    // График и таблица под графиком
    public function getPeriodReport($month, array $sites, $currency, $subdomains, $allStat, $group)
    {
        if(!count($sites) && ($group != 'all')) {
            return array();
        }
        
        $dataRequest = array(
            'method' => 'date_stat',
            'data' => array(
                'subdomains' => $subdomains,
                'month' => $month,
                'currency' => $currency
            )            
        );
        
        if ($allStat) {
            $dataRequest['data']['all_stat'] = true;
        }
        
        if ($group == 'all') {
            $dataRequest['data']['group'] = 'all';
        } else {
            $dataRequest['data']['domains'] = $sites;
        }
        
        $res = $this->apiRequest($dataRequest);
        
        $stats = $res['stat'] ?: array();                
        $dates = array(
            'min' => $res['min_month'] ? $res['min_month'].'-01' : date('Y-m-01'), 
            'max' => $res['max_month'] ? $res['max_month'].'-01' : date('Y-m-01'),
        );               
        
        //$dates = array('min' => date('Y-m', time()-86400*30*5), 'max' => date('Y-m'));                
        $current = new \DateTime();
        $start = \DateTime::createFromFormat('Y-m-d', $month.'-01');                                      
        
        if($start->format('Y-m') == $current->format('Y-m')) {
            $end = $current;
            $end->modify('+1 day'); // Для прогона цикла foreach $dateRange по всему интервалу включительно
        } else {
            $end = \DateTime::createFromFormat('Y-m-d', $month.'-01');                       
            $end->add(new \DateInterval('P'.$end->format('t').'D'));       
        }
        $dateRange = new \DatePeriod($start, new \DateInterval('P1D'), $end);
        
        $periodStats = array();
        foreach($dateRange as $date) {
            $dateValue = $date->format('Y-m-d');
            
            $periodStats['period'][] = $dateValue;
            $periodStats['hits'][] = intVal($stats[$dateValue]['hits']);
            $periodStats['money'][] = floatVal($stats[$dateValue]['money']);
            $periodStats['block_hits'][] = intVal($stats[$dateValue]['block_hits']);
            $periodStats['block_money'][] = floatVal($stats[$dateValue]['block_money']);
            if($allStat) {
                $periodStats['income'][] = floatVal($stats[$dateValue]['income']);
            }
            
        }
        
        return array($periodStats, $dates);
    }       
    
    // Данные по сайтам
    public function getSitesReport($month, array $sites, $currency, $subdomains, $allStat, $group)
    {
        if(!count($sites) && ($group != 'subdomain')) {
            return array();
        }
        
        $dataRequest = array(
            'method' => 'month_stat',
            'data' => array(
                'subdomains' => $subdomains,
                'month' => $month,
                'currency' => $currency,
                'group' => $group,
            )            
        );
        
        if ($allStat) {
            $dataRequest['data']['all_stat'] = true;
        }
        
        if ($group != 'subdomain') {
            $dataRequest['data']['domains'] = $sites;
        }
        
        $res = $this->apiRequest($dataRequest);
        
        if ($res == null)
        {
            $res = [];
            foreach($sites as $siteItem) {
                $res[] = array(
                    'site' => $siteItem,
                    'hits' => 0,
                    'money' => 0,
                    'block_hits' => 0,
                    'block_money' => 0,
                    'income' => 0
                );
            }
            usort($res, function ($f1,$f2){return ($f1['site'] < $f2['site']) ? -1 : 1;});
        }
        
        return $res;
    }
    
    // Данные по сайтам за вчерашние сутки
    public function getSitesReportYestarday($month, array $sites, $currency, $subdomains, $allStat, $group)
    {
        if(!count($sites) && ($group != 'subdomain')) {
            return array();
        }
        
        $dataRequest = array(
            'method' => 'site_stat',
            'data' => array(
                'subdomains' => $subdomains,
                'day' => $month,
                'currency' => $currency,
                'group' => $group,
                'all_stat' => true
            )            
        );
        
        $res = $this->apiRequest($dataRequest);
        
        return $res;
    }
    
    // Данные по метрикам
    public function getStatReport($metric, $type, $fields, $dates, $geo, $sites_id, $zones_id, $by_sites, $by_zones, $by_countries)
    {
        $timeDiff = (strtotime($dates[1])-strtotime($dates[0]))/(24*60*60);
        $by_days = (bool)$dates[2];
        $by_sites = (bool)$by_sites ? (int)$by_sites : false;
        $by_zones = (bool)$by_zones ? (int)$by_zones : false;
        $by_countries = (bool)$by_countries ? (int)$by_countries : false;
        
        foreach(['sspProvider', 'blockProvider', 'argonProvider', 'ndspProvider'] as $field) {
            $provider_field = (in_array($field, $fields)) ? $field : $provider_field;
        }
        $is_providers_metric = ($provider_field) ? true : false;
        
        // Определяем разрешение выборки (группировку) по времени:
        if ($timeDiff == 0) // Одни сутки
        {
            $dates_group = "Min";
        }
        elseif (!$by_days)  // Набор дат
        {
            $dates_group = ($is_providers_metric) ? "Day" : "Min";
        }
        else                // Несколько суток
        {
            $dates_group = "Day";
        }
        if ($by_sites || $by_zones || $by_countries)              // По сайтам, зонам, странам
        {
            $dates_group = ($timeDiff == 0) ? "Min" : "Day";
        }
        
        if ($by_days || $by_sites || $by_zones || $by_countries) {    // Диапазон дат или по сайтам, зонам странам
            $dates = array(
                'group' => $dates_group,
                'start'  => $dates[0], 
                'end'  => $dates[1],
            );
        } else {            // Набор дат
            $dates = array(
                'group' => $dates_group,
                'days'  => [$dates[0], $dates[1]],
            );
        }
        
        if ($metric == 'minstat') {
            if ($by_sites) $fields = array_merge($fields, ["SiteID"]);
            if ($by_zones) $fields = array_merge($fields, ["ZoneID"]);
            if ($by_countries) $fields = array_merge($fields, ["Country"]);
        }
        
        // Данные для запроса:
        $dataRequest = array(
            'method' => "reports",
            'data' => array(
                'type' => $type,
                'fields'  => $fields,
                'dates' => $dates,
            )      
        );
        
        // Фильтры:
        if ($geo != null) {
            $dataRequest['data']['filters']['Country'] = array(
                'values' => $geo['list'],
                'excl'   => (bool)$geo['exclude']
            );
        }
        if ($sites_id != null) {
            $dataRequest['data']['filters']['SiteID'] = array(
                'values' => $sites_id['list'],
                'excl'   => (bool)$sites_id['exclude']
            );
        }
        if ($zones_id != null) {
            $dataRequest['data']['filters']['ZoneID'] = array(
                'values' => $zones_id['list'],
                'excl'   => (bool)$zones_id['exclude']
            );
        }
        
        // Лимит:
        if ($metric == 'providersblockstat') {
            $dataRequest['data']['limit'] = 15;
        }
        if ($metric == 'minstat') {
            if ($by_sites) $dataRequest['data']['limit'] = $by_sites;
            if ($by_zones) $dataRequest['data']['limit'] = $by_zones;
            if ($by_countries) $dataRequest['data']['limit'] = $by_countries;
        }
        if ($metric == 'winstat') {
            $dataRequest['data']['limit'] = 10;
        }
                
        //return $dataRequest;
        $stats = $this->apiRequest($dataRequest);
        //return $stats;
        
        // В запросе ошибка или отсутствуют данные для статистики:
        if ($stats['status'] == 'Error') {
            return $stats;
        }
        if ($stats['data'] == []) {
            return null;
        }
        
        $dataStats = array();
        $period = array();
                
        // Метрики по сайтам, зонам, странам:
        if ($by_sites || $by_zones || $by_countries)
        {
            if ($by_sites) $cat_type = 'SiteID';
            if ($by_zones) $cat_type = 'ZoneID';
            if ($by_countries) $cat_type = 'Country';
            
            $list_sites = $this->sitesModel->createListSites();
            //$list_zones = $this->zonesModel->createListZones();
            if ($by_countries) {
                $list_codes = $this->countryCodes;
            }
            
            // Добавление категорий и полей в списки
            function AddCategories($category_data, &$all_categories_id, &$all_categories, &$all_cat, $list_sites, $list_zones, $list_codes, $metric, $cat_type)
            {
                foreach ($category_data as $category_id=>$category_value) {
                    
                    // Список зон:
                    if (!in_array($category_id, $all_categories_id)) {
                        $all_categories_id[] = $category_id;
                        
                        if ($cat_type == 'SiteID') {
                            $site_domain = ($list_sites[$category_id]) ? $list_sites[$category_id] : "_".$category_id;
                        }
                        if ($cat_type == 'ZoneID') {
                            //$site_id = $list_zones[$zone_id];
                            /*
                            if ($list_zones[$zone_id]) {
                                $site_id = $list_zones[$zone_id];
                            } else {
                                $site_id = floor($zone_id/100);
                            }
                            */
                            $site_id = floor($category_id/100);
                            $site_domain = ($list_sites[$site_id]) ? $list_sites[$site_id] : "_".$site_id;
                        }
                        if ($cat_type == 'Country') {
                            $site_domain = ($list_codes[$category_id]) ? $list_codes[$category_id] : '';
                        }
                        $all_categories[$category_id] = $site_domain;
                    }

                    // Список категорий:
                    if (count($all_cat)==0) {
                        foreach ($category_value as $cat=>$value) {
                            if (!in_array($cat, $all_cat)) {
                                $all_cat[] = $cat;
                            }
                        }
                        // Добавляем поля для метрики minstat:
                        if ($metric == 'minstat') {
                            $all_cat[] = 'cpm';
                            $all_cat[] = 'siteCpm';
                            $all_cat[] = 'systemCpm';
                            $all_cat[] = 'ctr';
                            $all_cat[] = 'cpc';
                            $all_cat[] = 'siteCpc';
                            $all_cat[] = 'systemCpc';
                            $all_cat[] = 'sspSystemMoney';
                            //$all_cat[] = 'sspMoneyAll';
                            $all_cat[] = 'sumRatio';
                            $all_cat[] = 'siteRatio';
                            $all_cat[] = 'systemRatio';
                        }
                    }
                }
            }
            
            // Формируем данные для временного промежутка
            function AddDataCategoriesStats(&$dataStats, $categories_data, $all_categories_id, $all_cat, $metric)
            {
                // Сайты (Зоны, Страны), данные для которых есть за текущий временной интервал:
                $time_categories = [];
                
                foreach ($categories_data as $category_id=>$category_value) {
                    
                    $time_categories[] = $category_id;
                    foreach ($category_value as $cat=>$value) {
                        $dataStats[$category_id][$cat][] = $value;
                    }
                    
                    // Добавляем поля для метрики minstat:
                    if ($metric == 'minstat') {
                        $dataStats[$category_id]['cpm'][] = ($category_value['sspViewsCnt'] == 0) ? 0 : $category_value['sspMoney'] / $category_value['sspViewsCnt'] * 1000;
                        $dataStats[$category_id]['siteCpm'][] = ($category_value['sspViewsCnt'] == 0) ? 0 : $category_value['sspSiteMoney'] / $category_value['sspViewsCnt'] * 1000;
                        $dataStats[$category_id]['systemCpm'][] = ($category_value['sspViewsCnt'] == 0) ? 0 : ($category_value['sspMoney'] - $category_value['sspSiteMoney']) / $category_value['sspViewsCnt'] * 1000;
                        
                        $dataStats[$category_id]['ctr'][] = ($category_value['sspViewsCnt'] == 0) ? 0 : $category_value['sspClicksCnt'] / $category_value['sspViewsCnt'] * 1;
                        
                        $dataStats[$category_id]['cpc'][] = ($category_value['sspClicksCnt'] == 0) ? 0 : $category_value['sspMoney'] / $category_value['sspClicksCnt'] * 100;
                        $dataStats[$category_id]['siteCpc'][] = ($category_value['sspClicksCnt'] == 0) ? 0 : $category_value['sspSiteMoney'] / $category_value['sspClicksCnt'] * 100;
                        $dataStats[$category_id]['systemCpc'][] = ($category_value['sspClicksCnt'] == 0) ? 0 : ($category_value['sspMoney'] - $category_value['sspSiteMoney']) / $category_value['sspClicksCnt'] * 100;
                        
                        $dataStats[$category_id]['sspSystemMoney'][] = $category_value['sspMoney'] - $category_value['sspSiteMoney'];
                        
                        $dataStats[$category_id]['sumRatio'][] = ($category_value['sspMoney'] == 0) ? 0 : $category_value['sspMoney'] / $category_value['sspMoney'] * 1;
                        $dataStats[$category_id]['siteRatio'][] = ($category_value['sspMoney'] == 0) ? 0 : $category_value['sspSiteMoney'] / $category_value['sspMoney'] * 1;
                        $dataStats[$category_id]['systemRatio'][] = ($category_value['sspMoney'] == 0) ? 0 : ($category_value['sspMoney'] - $category_value['sspSiteMoney']) / $category_value['sspMoney'] * 1;
                        
                        $all_cat[] = 'sumRatio';
                        $all_cat[] = 'siteRatio';
                        $all_cat[] = 'systemRatio';
                    }
                }

                // по провайдерам, которых нет выставляем нулевые значения:
                foreach ($all_categories_id as $category_id) {
                    if (!in_array($category_id, $time_categories)) {
                        foreach ($all_cat as $cat_name) {
                            $dataStats[$category_id][$cat_name][] = 0;
                        }
                    }
                }
            }
                        
            // Определяем списки всех зон и полей:
            $all_categories_id = [];
            $all_categories = [];
            $all_cat = [];
            
            foreach ($stats['data']['Day'] as $day) {
                // Одни сутки
                if ($day['Min']) {
                    foreach ($day['Min'] as $min=>$value_min) {
                        AddCategories($value_min[$cat_type], $all_categories_id, $all_categories, $all_cat, $list_sites, $list_zones, $list_codes, $metric, $cat_type);
                    }
                // Несколько суток (одни и более)    
                } else {
                    AddCategories($day[$cat_type], $all_categories_id, $all_categories, $all_cat, $list_sites, $list_zones, $list_codes, $metric, $cat_type);
                }
            }
            
            if ($timeDiff == 0) // Одни сутки
            {
                foreach ($stats['data']['Day'] as $day) {
                    foreach ($day['Min'] as $min=>$value_min) {
                        $period[] = date("H:i", strtotime($min));
                        AddDataCategoriesStats($dataStats, $value_min[$cat_type], $all_categories_id, $all_cat, $metric);
                    }
                }
            }
            else  // Несколько суток (двое и более)
            {
                foreach ($stats['data']['Day'] as $day=>$value_day) {
                    $period[] = $day;
                    AddDataCategoriesStats($dataStats, $value_day[$cat_type], $all_categories_id, $all_cat, $metric);
                }
            }
            
            $dataStats['type'] = ($timeDiff == 0) ? 'day' : 'interval';
            if ($by_sites) $dataStats['bySites'] = $all_categories;
            if ($by_zones) $dataStats['byZones'] = $all_categories;
            if ($by_countries) $dataStats['byCountries'] = $all_categories;
        }
        // Метрики по провайдерам:
        elseif ($is_providers_metric)
        {
            // Добавление провайдеров и полей в списки
            function AddItems($provider_data, &$all_providers, &$all_cat, $metric)
            {
                foreach ($provider_data as $provider=>$provider_value) {
                    // Список провайдеров:
                    $provider_name = ($provider != "") ? $provider : "unknown";
                    if (!in_array($provider_name, $all_providers)) {
                        $all_providers[] = $provider_name;
                    }

                    // Список категорий:
                    if (count($all_cat)==0) {
                        foreach ($provider_value as $cat=>$value) {
                            if (!in_array($cat, $all_cat)) {
                                $all_cat[] = $cat;
                            }
                        }
                        
                        // Добавляем поля в метрику bidstat:
                        if (in_array($metric, ['bidstat'])) {
                            $all_cat[] = 'cpm';
                        }
                        // Добавляем поля в метрику winstat:
                        if (in_array($metric, ['winstat'])) {
                            $all_cat[] = 'cpm';
                            $all_cat[] = 'ctr';
                            $all_cat[] = 'cpc';
                        }
                        // Добавляем поля в метрику providersblockstat:
                        if (in_array($metric, ['providersblockstat'])) {
                            $all_cat[] = 'ctr';
                            $all_cat[] = 'sum';
                        }
                        // Добавляем поля в метрику ndspstat:
                        if (in_array($metric, ['ndspstat'])) {
                            $all_cat[] = 'cpm';
                            $all_cat[] = 'ctr';
                            $all_cat[] = 'cpc';
                        }
                        
                    }
                }
                asort($all_providers);
            }
            
            // Формируем данные для временного промежутка
            function AddDataStats(&$dataStats, $providers_data, $all_providers, $all_cat, $metric)
            {
                // Провайдеры, данные для которых есть за текущий временной интервал:
                $time_providers = [];
                
                $min_koef = ($dataStats['type'] == 'interval') ? 1 : 5;

                foreach ($providers_data as $provider=>$provider_min_value) {

                    $provider_name = ($provider != "") ? $provider : "unknown";
                    $time_providers[] = $provider_name;

                    if ($provider_name == 'rtb') {
                        foreach ($provider_min_value as $cat=>$value) {
                            $provider_min_value['blockViewsCnt'] = $provider_min_value['sspViewsCnt'];
                            $provider_min_value['blockClicksCnt'] = $provider_min_value['sspClicksCnt'];
                        }
                    }
                    
                    foreach ($provider_min_value as $cat=>$value) {
                        $dataStats[$provider_name][$cat][] = $value/$min_koef;
                    }

                    // Добавляем поля для метрики bidstat:
                    if ($metric == 'bidstat') {
                        $dataStats[$provider_name]['cpm'][] = ($provider_min_value['bidCnt'] == 0) ? 0 : $provider_min_value['bidMoney'] / $provider_min_value['bidCnt'] * 1000;
                    }

                    // Добавляем поля для метрики winstat:
                    if ($metric == 'winstat') {
                        $dataStats[$provider_name]['cpm'][] = ($provider_min_value['sspViewsCnt'] == 0) ? 0 : $provider_min_value['sspMoney'] / $provider_min_value['sspViewsCnt'] * 1000;
                        $dataStats[$provider_name]['ctr'][] = ($provider_min_value['sspViewsCnt'] == 0) ? 0 : $provider_min_value['sspClicksCnt'] / $provider_min_value['sspViewsCnt'] * 1;
                        $dataStats[$provider_name]['cpc'][] = ($provider_min_value['sspClicksCnt'] == 0) ? 0 : $provider_min_value['sspMoney'] / $provider_min_value['sspClicksCnt'] * 100;
                    }
                    
                    // Добавляем поля для метрики providersblockstat:
                    if ($metric == 'providersblockstat') {
                        $dataStats[$provider_name]['ctr'][] = ($provider_min_value['blockViewsCnt'] == 0) ? 0 : $provider_min_value['blockClicksCnt'] / $provider_min_value['blockViewsCnt'] * 1;
                        $dataStats[$provider_name]['sum'][] = ($provider_min_value['blockViewsCnt'] + $provider_min_value['sspViewsCnt'])/$min_koef;
                    }
                    
                    // Добавляем поля для метрики ndspstat:
                    if ($metric == 'ndspstat') {
                        $dataStats[$provider_name]['cpm'][] = ($provider_min_value['adViewsCnt'] == 0) ? 0 : $provider_min_value['adMoney'] / $provider_min_value['adViewsCnt'] * 1000;
                        $dataStats[$provider_name]['ctr'][] = ($provider_min_value['adViewsCnt'] == 0) ? 0 : $provider_min_value['adClicksCnt'] / $provider_min_value['adViewsCnt'] * 1;
                        $dataStats[$provider_name]['cpc'][] = ($provider_min_value['adClicksCnt'] == 0) ? 0 : $provider_min_value['adMoney'] / $provider_min_value['adClicksCnt'] * 100;
                    }
                }

                // по провайдерам, которых нет выставляем нулевые значения:
                foreach ($all_providers as $provider_name) {
                    if (!in_array($provider_name, $time_providers)) {
                        foreach ($all_cat as $cat_name) {
                            $dataStats[$provider_name][$cat_name][] = 0;
                        }
                    }
                }
            }
            
            // Определяем списки всех провайдеров и полей:
            $all_providers = [];
            $all_cat = [];
            foreach ($stats['data']['Day'] as $day) {
                // Одни сутки
                if ($day['Min']) {
                    foreach ($day['Min'] as $min=>$value_min) {
                        AddItems($value_min[$provider_field], $all_providers, $all_cat, $metric);
                    }
                // Несколько суток (одни и более)    
                } else {
                    AddItems($day[$provider_field], $all_providers, $all_cat, $metric);
                }
            }
            
            if ($timeDiff == 0) // Одни сутки
            {
                $dataStats['type'] = 'day';
                foreach ($stats['data']['Day'] as $day) {
                    foreach ($day['Min'] as $min=>$value_min) {
                        $period[] = date("H:i", strtotime($min));
                        AddDataStats($dataStats, $value_min[$provider_field], $all_providers, $all_cat, $metric);
                    }
                }
            }
            else  // Несколько суток (двое и более)
            {
                $dataStats['type'] = 'interval';
                foreach ($stats['data']['Day'] as $day=>$value_day) {
                    $period[] = $day;
                    AddDataStats($dataStats, $value_day[$provider_field], $all_providers, $all_cat, $metric);
                }
            }
            
        } 
        // Обычные метрики
        else
        {
            // Формируем данные для временного промежутка
            function AddDataStats(&$data_stats, $data, $metric, $date_type)
            {
                $min_koef = ($date_type == 'interval') ? 1 : 5;
                
                foreach ($data as $cat=>$value) {
                    $data_stats[$cat][] = $value/$min_koef;
                }

                // Добавляем поля для метрики pagestat:
                if ($metric == 'pagestat') {
                    $data_stats['runRatio'][] = ($data['loadCnt'] == 0) ? 0 : $data['runCnt'] / $data['loadCnt'] * 1;
                }

                // Добавляем поля для метрики minstat:
                if ($metric == 'minstat') {
                    $data_stats['cpm'][] = ($data['sspViewsCnt'] == 0) ? 0 : $data['sspMoney'] / $data['sspViewsCnt'] * 1000;
                    $data_stats['siteCpm'][] = ($data['sspViewsCnt'] == 0) ? 0 : $data['sspSiteMoney'] / $data['sspViewsCnt'] * 1000;
                    $data_stats['systemCpm'][] = ($data['sspViewsCnt'] == 0) ? 0 : ($data['sspMoney'] - $data['sspSiteMoney']) / $data['sspViewsCnt'] * 1000;
                    $data_stats['ctr'][] = ($data['sspViewsCnt'] == 0) ? 0 : $data['sspClicksCnt'] / $data['sspViewsCnt'] * 1;
                    $data_stats['cpc'][] = ($data['sspClicksCnt'] == 0) ? 0 : $data['sspMoney'] / $data['sspClicksCnt'] * 100;
                    $data_stats['siteCpc'][] = ($data['sspClicksCnt'] == 0) ? 0 : $data['sspSiteMoney'] / $data['sspClicksCnt'] * 100;
                    $data_stats['systemCpc'][] = ($data['sspClicksCnt'] == 0) ? 0 : ($data['sspMoney'] - $data['sspSiteMoney']) / $data['sspClicksCnt'] * 100;
                    $data_stats['sspSystemMoney'][] = ($data['sspMoney'] - $data['sspSiteMoney'])/$min_koef;
                    //$data_stats['sspMoneyAll'][] = ($data['sspMoney'] + $data['sspSiteMoney'])/$min_koef;
                    $data_stats['sumRatio'][] = ($data['sspMoney'] == 0) ? 0 : $data['sspMoney'] / $data['sspMoney'] * 1;
                    $data_stats['siteRatio'][] = ($data['sspMoney'] == 0) ? 0 : $data['sspSiteMoney'] / $data['sspMoney'] * 1;
                    $data_stats['systemRatio'][] = ($data['sspMoney'] == 0) ? 0 : ($data['sspMoney'] - $data['sspSiteMoney']) / $data['sspMoney'] * 1;
                }
                
                // Добавляем поля для метрики ndspstat:
                if ($metric == 'ndspstat') {
                    $data_stats['cpm'][] = ($data['adViewsCnt'] == 0) ? 0 : $data['adMoney'] / $data['adViewsCnt'] * 1000;
                    $data_stats['ctr'][] = ($data['adViewsCnt'] == 0) ? 0 : $data['adClicksCnt'] / $data['adViewsCnt'] * 1;
                    $data_stats['cpc'][] = ($data['adClicksCnt'] == 0) ? 0 : $data['adMoney'] / $data['adClicksCnt'] * 100;
                }

                // Добавляем поля для метрики blockstat:
                if ($metric == 'blockstat') {
                    //$data_stats['sum'][] = $data['blockViewsCnt'] + $data['sspViewsCnt'];
                    //$data_stats['ctr'][] = ($data['blockViewsCnt'] == 0) ? 0 : $data['blockClicksCnt'] / $data['blockViewsCnt'] * 1;
                    $data_stats['sumViews'][] = ($data['blockViewsCnt'] + $data['sspViewsCnt'])/$min_koef;
                    $data_stats['sumClicks'][] = ($data['blockClicksCnt'] + $data['sspClicksCnt'])/$min_koef;
                    $data_stats['ctr'][] = ($data['blockViewsCnt'] == 0) ? 0 : $data['blockClicksCnt'] / $data['blockViewsCnt'] * 1;
                    $data_stats['ctrRtb'][] = ($data['sspViewsCnt'] == 0) ? 0 : $data['sspClicksCnt'] / $data['sspViewsCnt'] * 1;
                }
            }
        
            if ($timeDiff == 0) // Одни сутки
            {
                $dataStats['type'] = 'day';
                
                // Формируем пустые данные (для отсутствующих значений во временной точке):
                foreach ($stats['data']['Day'] as $day=>$value_day) {
                    foreach ($value_day['Min'] as $min=>$data) {
                        $data_null = $data;
                        break;
                    }
                    break;
                }
                foreach ($data_null as $key=>$value) {
                    $data_null[$key] = 0;
                }
                // Формируем 5-минутные интервалы:
                for ($i=0; $i<288; $i++) {
                    $min = $i * 60 * 5;
                    $period[] = gmdate("H:i", $min);
                }
                
                foreach ($stats['data']['Day'] as $day) {
                    // Формируем временные интервалы, для которых есть значения:
                    $dates_min = [];
                    foreach (array_keys($day['Min']) as $min) {
                        $dates_min[date("H:i", strtotime($min))] = $min;
                    }
                    
                    foreach ($period as $min_value) {
                        $value_min = ($dates_min[$min_value]) ? $day['Min'][$dates_min[$min_value]] : $data_null;
                        AddDataStats($dataStats, $value_min, $metric, $dataStats['type']);
                    }
                }
                
            }
            elseif (!$by_days) // Набор дат
            {
                $dataStats['type'] = 'compare';
                
                // Формируем пустые данные (для отсутствующих значений во временной точке):
                foreach ($stats['data']['Day'] as $day=>$value_day) {
                    foreach ($value_day['Min'] as $min=>$data) {
                        $data_null = $data;
                        break;
                    }
                    break;
                }
                foreach ($data_null as $key=>$value) {
                    $data_null[$key] = 0;
                }
                // Формируем 5-минутные интервалы:
                for ($i=0; $i<288; $i++) {
                    $min = $i * 60 * 5;
                    $period[] = gmdate("H:i", $min);
                }
                
                foreach ($stats['data']['Day'] as $day=>$value_day) {
                    $dataStats[date("Y-m-d", strtotime($day))] = [];
                    // Формируем временные интервалы, для которых есть значения:
                    $dates_min = [];
                    foreach (array_keys($value_day['Min']) as $min) {
                        $dates_min[date("H:i", strtotime($min))] = $min;
                    }
                    
                    foreach ($period as $min_value) {
                        $data = ($dates_min[$min_value]) ? $value_day['Min'][$dates_min[$min_value]] : $data_null;
                        AddDataStats($dataStats[date("Y-m-d", strtotime($day))], $data, $metric, $dataStats['type']);
                    }
                }
                
            }
            else // Несколько суток
            {
                $dataStats['type'] = 'interval';
                foreach ($stats['data']['Day'] as $day=>$value_day) {
                    $period[] = $day;
                    AddDataStats($dataStats, $value_day, $metric, $dataStats['type']);
                }
            }

        }
        
        $dataStats['period'] = $period;
        $dataStats['metric'] = $metric;
        
        $stats = $dataStats;
        return $stats;
    }
    
    // Популярные страны по метрикам:
    public function getStatReportCountries($type, $fields) {
        
        foreach(['sspProvider', 'blockProvider', 'argonProvider'] as $field) {
            $provider_field = (in_array($field, $fields)) ? $field : $provider_field;
        }
        $is_providers_metric = ($provider_field) ? true : false;
        
        $start = ($is_providers_metric) ? 120 : 7;
        
        $dataRequest = array(
            'method' => "reports",
            'data' => array(
                'type' => $type,
                'fields'  => array_merge($fields, ["Country"]),
                'dates' => array(
                    'group' => "Day",
                    'start'  => date("Y-m-d", strtotime(date("Y-m-d"))-$start*24*60*60),
                    'end'  => date("Y-m-d"),
                ),
            )      
        );
        
        $stats = $this->apiRequest($dataRequest);
        
        $countries_codes = [];
        if ($is_providers_metric)
        {
            foreach ($stats['data']['Day'] as $day) {
                foreach ($day[$provider_field] as $provider=>$data) {
                    $day_countries = array_keys($data['Country']);
                    foreach ($day_countries as $code) {
                        if (!in_array($code, array_keys($countries_codes))) {
                            $countries_codes[$code] = 1;
                        } else {
                            $countries_codes[$code]++;
                        }
                    }
                }
            }
        }
        else
        {
            foreach ($stats['data']['Day'] as $day) {
                $day_countries = array_keys($day['Country']);
                foreach ($day_countries as $code) {
                    if (!in_array($code, array_keys($countries_codes))) {
                        $countries_codes[$code] = 1;
                    } else {
                        $countries_codes[$code]++;
                    }
                }
            }
        } 
        
        arsort($countries_codes);
        $popular_countries = array_slice($countries_codes,0,5);
        
        return $popular_countries;
    }
    
    // Codestat global - сводная таблица над графиком
    public function getCodestatGlobalReport(array $sites, $codes)
    {
        if(!count($sites)) {
            return array();
        }                
        
        $dataRequest = array(
            'method' => 'code_global_stat',
            'data' => array(
                'codes' => $codes, //["adpartner"]
                'sites' => $sites, //[50000, 50095]
                'currency' => "USD"
            )
        );
        
        $report = $this->apiRequest($dataRequest);
        
        // Добавляем поле CTR:
        if ($report['stat']) {
            foreach($report['stat'] as $period=>$data) {
                $report['stat'][$period]['ctr'] = ($data['views'] == 0) ? 0 : $data['clicks'] / $data['views'] * 1;
            }
        }
        
        $report = $report['stat'] ?: array();
        return $report;
    }
    
    // Codestat - график и таблица под графиком
    public function getCodestatReport($month, array $sites, $codes)
    {
        //$month = "2018-04";
        $dataRequest = array(
            'method' => 'code_date_stat',
            'data' => array(
                'codes' => $codes, //["adpartner"]
                'sites' => $sites, //[50000, 50095]
                'month' => $month,
                'currency' => "USD",
            )
        );
        
        $res = $this->apiRequest($dataRequest);
        
        $stats = $res['stat'] ?: array();                
        $dates = array(
            'min' => $res['min_month'] ? $res['min_month'].'-01' : date('Y-m-01'), 
            'max' => $res['max_month'] ? $res['max_month'].'-01' : date('Y-m-01'),
        );               
        
        $current = new \DateTime();
        $start = \DateTime::createFromFormat('Y-m-d', $month.'-01');                                      
        
        if($start->format('Y-m') == $current->format('Y-m')) {
            $end = $current;
            $end->modify('+1 day');
        } else {
            $end = \DateTime::createFromFormat('Y-m-d', $month.'-01');                       
            $end->add(new \DateInterval('P'.$end->format('t').'D'));       
        }
        $dateRange = new \DatePeriod($start, new \DateInterval('P1D'), $end);
        
        
        $periodStats = array();
        foreach($dateRange as $date) {
            $dateValue = $date->format('Y-m-d');
            
            $periodStats['period'][] = $dateValue;
            $views_value = intVal($stats[$dateValue]['views']);
            $clicks_value = intVal($stats[$dateValue]['clicks']);
            $periodStats['views'][] = $views_value;
            $periodStats['clicks'][] = $clicks_value;
            $periodStats['ctr'][] = ($views_value == 0) ? 0 : $clicks_value / $views_value * 1;
        }
        
        return array($periodStats, $dates);
    }
    
    
    
    // Запрос к API:
    private function apiRequest($data) 
    {
        $playload = json_encode($data);
        
        $url = 'http://stat.instraroam.net/json/'.md5($playload . $this->hashSolt);
        //$url = 'https://9261bdc7.ngrok.io/json/'.md5($playload . $this->hashSolt);
        
        $cl = curl_init();
        curl_setopt($cl, CURLOPT_URL, $url);
        curl_setopt($cl, CURLOPT_POST, true);
        curl_setopt($cl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($cl, CURLOPT_HTTPHEADER, array(
            'Content-Type:application/json'
        ));        
        curl_setopt($cl, CURLOPT_POSTFIELDS, $playload);
        
        $result = curl_exec($cl);
        $info = curl_getinfo($cl);
        curl_close($cl);
        
        if($info['http_code'] != 200) {
            throw new \Exception('Error. ' . $info['http_code']);
            //throw new \Exception('Error. ' . $info['http_code'] . ' json-data: '. json_encode($data)); // для передачи данных json-запроса
        }
        
        return json_decode($result, 1);
    }
    
}
