<?php

class actionAdminIndexChartData extends cmsAction {

    private $date_formates = [
        'DAY' => [
            'format' => 'd.m',
            'format_diff' => '-%s days',
            'format_diff_keys' => '-%s days',
            'divisor' => 1
        ],
        'WEEK' => [
            'format' => 'd.m',
            'format_diff' => '-%s week',
            'format_diff_keys' => '-%s days',
            'divisor' => 1
        ],
        'MONTH' => [
            'format' => 'd.m',
            'format_diff' => '-%s months',
            'format_diff_keys' => '-%s days',
            'divisor' => 1
        ],
        'YEAR' => [
            'format' => 'm.Y',
            'format_diff' => '-%s year',
            'format_diff_keys' => '-%s months',
            'divisor' => 30
        ]
    ];

    private $interval = 'DAY';

    private function df($key) {
        return $this->date_formates[$this->interval][$key];
    }

    public function run() {

        if (!$this->request->isAjax()) {
            return cmsCore::error404();
        }

        $id      = $this->request->get('id', '');
        $section = $this->request->get('section', '');
        $period  = $this->request->get('period', 0);

        $this->interval = $this->request->get('interval', '');

        if (!$period && !$this->interval) {
            return cmsCore::error404();
        }

        if ($this->interval) {

            list($period, $this->interval) = explode(':', $this->interval);

            if (!is_numeric($period)) {
                return cmsCore::error404();
            }

            $this->interval = strtoupper($this->interval);

            if (!isset($this->date_formates[$this->interval])) {
                return cmsCore::error404();
            }

        } else {

            $this->interval = 'DAY';

            if($period >= 365){

                $this->interval = 'YEAR';

                $period = (int)$period/365;
            }
        }

        if (!in_array($this->interval, array_keys($this->date_formates), true)) {
            return cmsCore::error404();
        }

        if (!$id || !$section) {
            return cmsCore::error404();
        }

        $chart_nav = cmsEventsManager::hookAll('admin_dashboard_chart');

        $sources = $old_result = $chart_data = [];

        foreach ($chart_nav as $ctrl) {
            if ($ctrl['id'] == $id) {
                foreach ($ctrl['sections'] as $key => $s) {
                    if ($key == $section || strpos($key, $section . ':') === 0) {
                        $sources[] = $ctrl['sections'][$key];
                    }
                }
            }
        }

        if (!$sources) {
            return cmsCore::error404();
        }

        foreach ($sources as $source) {

            $result = $data_formatted = [];

            $data = $this->getData($source, $period);

            foreach ($data as $item) {
                $data_formatted[date($this->df('format'), strtotime($item['date']))] = (int)$item['count'];
            }

            $diff_time = strtotime(sprintf($this->df('format_diff'), $period));

            $now_date = new DateTime();
            $prev_date = new DateTime('@'.$diff_time);

            $days = (int)$now_date->diff($prev_date)->days/$this->df('divisor');

            for ($d = 0; $d <= $days; $d++) {

                $date = date($this->df('format'), strtotime(sprintf($this->df('format_diff_keys'), $d)));

                $result[$date] = isset($data_formatted[$date]) ? $data_formatted[$date] : 0;
            }

            $result = array_reverse($result);

            // совместимость
            // теперь можно отдавать данные
            // для нескольких графиков
            if (!$old_result) {
                $old_result = $result;
            }

            if (!$chart_data) {
                $chart_data = [
                    'labels'   => array_keys($result),
                    'datasets' => [
                        $this->getDsParams($source, $result)
                    ]
                ];
            } else {
                $chart_data['datasets'][] = $this->getDsParams($source, $result);
            }
        }

        $footer_data = $footer_result = [];

        foreach ($chart_nav as $ctrl) {
            if ($ctrl['id'] == $id && isset($ctrl['footer'][$section])) {
                $footer_data = $ctrl['footer'][$section];
                break;
            }
        }

        if ($footer_data) {
            foreach ($footer_data as $fdata) {
                $footer_result[] = [
                    'count'    => $this->getFooterData($fdata),
                    'title'    => $fdata['title'],
                    'progress' => $fdata['progress']
                ];
            }
        }

        $this->cms_template->renderJSON([
            // это совместимость
            'labels' => array_keys($old_result),
            'values' => array_values($old_result),
            // это новый формат отдачи
            'result' => [
                'chart_data' => $chart_data,
                'footer'     => $footer_result
            ]
        ]);
    }

    private function getDsParams($source, $result) {
        return [
            'data'                      => array_values($result),
            'label'                     => (isset($source['hint']) ? $source['hint'] : (isset($source['title']) ? $source['title'] : '')),
            'backgroundColor'           => (isset($source['style']['bg_color']) ? $source['style']['bg_color'] : 'rgba(32, 168, 216, 0.1)'),
            'borderColor'               => (isset($source['style']['border_color']) ? $source['style']['border_color'] : 'rgba(32, 168, 216)'),
            'pointHoverBackgroundColor' => '#fff',
            'borderWidth'               => 2
        ];
    }

    private function getData($source, $period) {

        $this->model->
                selectOnly($source['key'], 'date')->
                select('COUNT(1)', 'count')->
                filterFunc($source['key'], "(CURDATE() - INTERVAL {$period} {$this->interval})", '>=');

        // совместимость
        if (isset($source['filter'])) {
            $source['filters'] = $source['filter'];
            unset($source['filter']);
        }

        $this->model->applyDatasetFilters($source, true);

        if($this->interval === 'DAY'){
            $this->model->group_by = $period < 365 ? "MONTH({$source['key']}), DAY({$source['key']})" : "EXTRACT(YEAR_MONTH FROM {$source['key']})";
        } elseif($this->interval !== 'YEAR') {
            $this->model->group_by = "MONTH({$source['key']}), DAY({$source['key']})";
        } else {
            $this->model->group_by = "EXTRACT(YEAR_MONTH FROM {$source['key']})";
        }

        return $this->model->get($source['table'], false, false) ?: [];
    }

    private function getFooterData($source) {

        $this->model->applyDatasetFilters($source, true);

        return $this->model->getCount($source['table'], 'id', true);
    }

}
