<?php

namespace App\Model;

use DateTime;

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

    
    // Данные по отчетам фидов
    public function getFeedStatData($report_type, $feed_id_list, $dates, $report_conf)
    {
        
        $timeDiff = (strtotime($dates[1])-strtotime($dates[0]))/(24*60*60);
        // Определяем разрешение выборки (группировку) по времени:
        if ($timeDiff == 0) // Одни сутки
        {
            $dates_group = "Min";
        }
        else                // Несколько суток
        {
            $dates_group = "Day";
        }
        
        $dates = array(
            'group' => $dates_group,
            'start'  => $dates[0], 
            'end'  => $dates[1],
        );
        
        // Параметры запроса по типу отчета:
        $type = $report_conf['type'];
        $fields = $report_conf['fields'];
                
        // Данные для запроса:
        if ($report_type == 'common') {
            $dataRequest = array(
                'method' => "reports",
                'data' => array(
                    'type' => $type,
                    'filters'  => array(
                        'FeedID' => array('values' => $feed_id_list),
                    ),
                    'fields'  => $fields,
                    'dates' => $dates,
                )      
            );
        }
        
        if ($report_type == 'transactions') {
            $dataRequest = array(
                'method' => $type,
                'data' => array(
                    'feed_id' => $feed_id_list,
                    'start_date' => $dates['start'],
                    'end_date' => $dates['end'],
                )      
            );
        }
        
        //return $dataRequest;
        //$stats = $this->apiRequest($dataRequest);
        //return $stats;
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
        }
        //return $stats;

        
        // В запросе ошибка или отсутствуют данные для статистики:
        if ($stats['status'] == 'Error') {
            return $stats;
        }
        if ($stats['data'] == []) {
            return null;
        }
        
        $dataStats = array();
        $dataStats['report'] = $report_type;
        
        // Данные для отчета 'common':
        if ($report_type == 'common') {
        
            $period = array();

            // Формируем данные для временного промежутка
            function AddDataStats(&$data_stats, $data, $date_type)
            {
                $min_koef = ($date_type == 'interval') ? 1 : 5;
                foreach ($data as $cat=>$value) {
                    $data_stats[$cat][] = $value/$min_koef;
                }
                //$data_stats['AdMoney'][] = 224 * $data['Orders']; // временно
            }
            
            function AddDataStatsFixedAdMoney(&$data_stats, $data, $date_type)
            {
                foreach ($data as $cat=>$value) {
                    if ($cat == 'AdMoney') {
                        $data_stats['AdMoney'][] = 224 * $data['Orders'];
                    } else {
                        $data_stats[$cat][] = $value;
                    }
                }
            }

            // Формируем пустые данные для временного промежутка
            function AddDataStatsNull(&$data_stats, $cats)
            {
                foreach ($cats as $cat) {
                    $data_stats[$cat][] = 0;
                }
                //$data_stats['AdMoney'][] = 0; // временно
            }

            // Логика формирования данных по временному интервалу:
            /*
            if (false) {
                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['type'] = 'interval';

            // Спискок всех дат из запроса стастистики:
            $all_period = array();
            $begin = new DateTime($dates['start']);
            $end   = new DateTime($dates['end']);
            for($i = $begin; $i <= $end; $i->modify('+1 day')){
                $all_period[] = $i->format("Y-m-d");
            }

            // Список дат, полученных в статистике: 
            $stat_days = array_keys($stats['data']['Day']);
            // Список категорий в данных статистики: 
            $stat_cats = array_keys($stats['data']['Day'][$stat_days[0]]);

            foreach ($all_period as $day_item) {
                $item = new DateTime($day_item);
                $stat_from = new DateTime($stat_days[0]);
                $stat_to = new DateTime($stat_days[count($stat_days)-1]);

                //if (($item>= $stat_from) && ($item<= $stat_to)) {
                if (($item>= $stat_from)) {
                    $period[] = $day_item;
                    if ($stats['data']['Day'][$day_item]) {
                        AddDataStats($dataStats, $stats['data']['Day'][$day_item], $dataStats['type']);
                        /*
                        if (strtotime($day_item)< strtotime('2019-04-01')) {
                            AddDataStatsFixedAdMoney($dataStats, $stats['data']['Day'][$day_item], $dataStats['type']);
                        } else {
                            AddDataStats($dataStats, $stats['data']['Day'][$day_item], $dataStats['type']);
                        }
                        */
                    } else {
                        AddDataStatsNull($dataStats, $stat_cats);
                    }
                }
            }

            /*
            foreach ($stats['data']['Day'] as $day=>$value_day) {
                $period[] = $day;
                AddDataStats($dataStats, $value_day, $dataStats['type']);
            }
            */
            
            $dataStats['period'] = $period;
        }
        
        // Данные для отчета 'transactions':
        if ($report_type == 'transactions') {
            foreach ($stats['data'] as $item) {
                $dataStats['period'][] = [$item['ForeignID'], $item['FeedID']];
                $dataStats['ViewID'][] = $item['ViewID'];
                $dataStats['Timestamp'][] = $item['Timestamp'];
                $dataStats['OrderSum'][] = $item['OrderSum'];
                $dataStats['Basket'][] = $item['Basket'];
                $dataStats['AdMoney'][] = $item['AdMoney'];
                /*
                if (strtotime($item['Timestamp'])< strtotime('2019-04-01')) {
                    $dataStats['AdMoney'][] = 224;
                } else {
                    $dataStats['AdMoney'][] = $item['AdMoney'];
                }
                */
            }
        }
        
        $stats = $dataStats;
        return $stats;
    }
    
    // Данные по статистике по клику
    public function getViewIdStatData($feed_id, $view_id)
    {
        
        $dataRequest = array(
            'method' => 'feed_click_history',
            'data' => array(
                'feed_id' => (int) $feed_id,
                'view_id' => $view_id
            )      
        );
        
        //return $dataRequest;
        //$stats = $this->apiRequest($dataRequest);
        //return $stats;
        
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
        }
        
        // В запросе ошибка или отсутствуют данные для статистики:
        if ($stats['status'] == 'Error') {
            return $stats;
        }
        if ($stats['data'] == []) {
            return null;
        }
        
        $stats = $stats['data'];
        return $stats;
    }
    
    // Данные по статистике по заказу фида
    public function getOrderIdStatData($feed_id, $order_id)
    {
        $dataRequest = array(
            'method' => 'feed_order_history',
            'data' => array(
                'feed_id' => (int) $feed_id,
                'order_id' => $order_id
            )      
        );
        
        //return $dataRequest;
        //$stats = $this->apiRequest($dataRequest);
        //return $stats;
        
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
        }
        
        // В запросе ошибка или отсутствуют данные для статистики:
        if ($stats['status'] == 'Error') {
            return $stats;
        }
        if ($stats['data'] == []) {
            return null;
        }
        
        $stats = $stats['data'];
        return $stats;
    }
    
    // Данные для статистики по кампании (баннеры)
    public function getCampaignsStat($id_list, $taget_action, $dates)
    {
        $dataRequest = array(
            'method' => ($dates) ? 'camp_day' : 'camp_total',
            'data' => array(
                'ids' => $id_list,
            )      
        );
        
        if ($dates) {
            $dataRequest['data']['start_date'] = $dates[0];
            $dataRequest['data']['end_date'] = $dates[1];
            $dataRequest['data']['by_days'] = true;
        }
        
        //return $dataRequest;
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
            return $stats;
        }
        //return $stats;
        
        if ($stats) {
            
            // Добавляем спец. поля
            $AddSpecialFields = function(&$stats)
            {
                if ($taget_action == 'load') {
                    $stats['views'] = $stats['loads'];
                    $stats['reach'] = $stats['reach_load'];
                } else {
                    $stats['reach'] = $stats['reach_view'];
                }
                unset($stats['loads']);
                unset($stats['reach_load']);
                unset($stats['reach_view']);

                $views = $stats['views'];
                $money = $stats['money'];
                $clicks = $stats['clicks'];

                $stats['ctr'] = ($views != 0) ? round(($clicks/$views)*100, 2) : 0;
                $stats['cpm'] = ($views != 0) ? round(($money/$views)*1000, 3) : 0;
                $stats['cpc'] = ($clicks != 0) ? round(($money/$clicks)*100, 1) : 0;

                $stats['money'] = round($stats['money'], 2);
            };
            
            if (!$dates)
            {
                $AddSpecialFields($stats);
                $dataStats = $stats;
            }
            else
            {
                foreach ($stats as $day => $stat) {
                    $AddSpecialFields($stats[$day]);
                }
                
                // Формируем данные для временного промежутка
                function AddDataStats(&$data_stats, $data)
                {
                    foreach ($data as $cat=>$value) {
                        $data_stats[$cat][] = $value;
                    }
                }
                
                // Формируем пустые данные для временного промежутка
                function AddDataStatsNull(&$data_stats, $cats)
                {
                    foreach ($cats as $cat) {
                        $data_stats[$cat][] = 0;
                    }
                }

                // Спискок всех дат из запроса стастистики:
                $all_period = array();
                $begin = new DateTime($dates[0]);
                $end   = new DateTime($dates[1]);
                for($i = $begin; $i <= $end; $i->modify('+1 day')){
                    $all_period[] = $i->format("Y-m-d");
                }

                // Список дат, полученных в статистике: 
                $stat_days = array_keys($stats);
                
                // Список категорий в данных статистики: 
                $stat_cats = array_keys($stats[$stat_days[0]]);

                $dataStats = [];
                
                foreach ($all_period as $day_item) {
                    $item = new DateTime($day_item);
                    $stat_from = new DateTime($stat_days[0]);
                    $stat_to = new DateTime($stat_days[count($stat_days)-1]);

                    //if (($item >= $stat_from) && ($item <= $stat_to)) {
                    //if (($item >= $stat_from)) {
                    if (($item <= $stat_to)) {
                        $period[] = $day_item;
                        if ($stats[$day_item]) {
                            AddDataStats($dataStats, $stats[$day_item]);
                        } else {
                            AddDataStatsNull($dataStats, $stat_cats);
                        }
                    }
                }

                $dataStats['period'] = $period;
            }
        }
        
        return $dataStats;
    }
        
    // Данные для статистики по баннерам
    public function getBannersStat($banners_id_list, $dates)
    {
        $dataRequest = array(
            'method' => ($dates) ? 'banner_day' : 'banner_total',
            'data' => array(
                'ids' => $banners_id_list,
            )      
        );
        
        if ($dates) {
            $dataRequest['data']['start_date'] = $dates[0];
            $dataRequest['data']['end_date'] = $dates[1];
        }
        
        //return $dataRequest;
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
        }
        return $stats;
    }
    
    // Данные для статистики кампании по сайтам
    public function getCampaignsSitesStat($id, $taget_action, $dates)
    {
        
        $dataRequest = array(
            'method' => 'camp_zone',
            'data' => array(
                'id' => $id,
                'start_date' => $dates[0],
                'end_date' => $dates[1]
            )      
        );
        
        //return $dataRequest;
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
            return $stats;
        }
        //return $stats;
        
        if ($stats) {
            
            // Добавляем спец. поля
            $AddSpecialFields = function(&$stats)
            {
                if ($taget_action == 'load') {
                    $stats['views'] = $stats['loads'];
                    $stats['reach'] = $stats['reach_load'];
                } else {
                    $stats['reach'] = $stats['reach_view'];
                }
                unset($stats['loads']);
                unset($stats['reach_load']);
                unset($stats['reach_view']);

                $views = $stats['views'];
                $money = $stats['money'];
                $clicks = $stats['clicks'];

                $stats['ctr'] = ($views != 0) ? round(($clicks/$views)*100, 2) : 0;
                $stats['cpm'] = ($views != 0) ? round(($money/$views)*1000, 3) : 0;
                $stats['cpc'] = ($clicks != 0) ? round(($money/$clicks)*100, 1) : 0;

                $stats['money'] = round($stats['money'], 2);
            };
            
            foreach ($stats as $site => $stat) {
                $AddSpecialFields($stats[$site]);
                if ($stat['sub']) {
                    foreach ($stat['sub'] as $sub => $stat) {
                        $AddSpecialFields($stats[$site]['sub'][$sub]);
                    }
                }
            }
            
            $dataStats = $stats;
        }
        
        return $dataStats;
    }
            
    // Данные для статистики кампании по регионам
    public function getCampaignsRegionsStat($id, $taget_action, $dates)
    {
        $dataRequest = array(
            'method' => 'camp_geo',
            'data' => array(
                'id' => $id,
                'start_date' => $dates[0],
                'end_date' => $dates[1]
            )      
        );
        
        //return $dataRequest;
        try {
            $stats = $this->apiRequest($dataRequest);
        } catch (\Exception $e) {
            $stats['status'] = 'Error';
            return $stats;
        }
        //return $stats;
        
        if ($stats) {
            
            // Добавляем спец. поля
            $AddSpecialFields = function(&$stats)
            {
                if ($taget_action == 'load') {
                    $stats['views'] = $stats['loads'];
                    $stats['reach'] = $stats['reach_load'];
                } else {
                    $stats['reach'] = $stats['reach_view'];
                }
                unset($stats['loads']);
                unset($stats['reach_load']);
                unset($stats['reach_view']);

                $views = $stats['views'];
                $money = $stats['money'];
                $clicks = $stats['clicks'];

                $stats['ctr'] = ($views != 0) ? round(($clicks/$views)*100, 2) : 0;
                $stats['cpm'] = ($views != 0) ? round(($money/$views)*1000, 3) : 0;
                $stats['cpc'] = ($clicks != 0) ? round(($money/$clicks)*100, 1) : 0;

                $stats['money'] = round($stats['money'], 2);
            };
            
            foreach ($stats as $region => $stat) {
                $AddSpecialFields($stats[$region]);
                if ($stat['sub']) {
                    foreach ($stat['sub'] as $sub => $stat) {
                        $AddSpecialFields($stats[$region]['sub'][$sub]);
                    }
                }
            }
            
            $dataStats = $stats;
        }
        
        return $dataStats;
    }
    
    
    
    // Запрос к 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']);
        }
        
        return json_decode($result, 1);
    }
    
}
