<?php

namespace Salesloo\Admin;

use \Salesloo\Admin_Ajax;

/**
 * Admin Affiliate Page classes
 */
class Affiliate
{
    private $admin_ajax;

    public $affiliate_id;

    /**
     * table
     *
     * @var array
     */
    private $table;

    /**
     * args
     *
     * @var array
     */
    private $args;

    /**
     * __construct
     *
     * @return void
     */
    public function __construct()
    {

        $this->admin_ajax = new Admin_Ajax;

        $this->affiliate_id = isset($_GET['affiliate_id']) ? intval($_GET['affiliate_id']) : 0;
    }

    /**
     * return dashboard template
     *
     * @return void
     */
    public function template()
    {
        salesloo_hidding_wp_admin_notices();

        $x_data = [
            'filter' => [
                'product_id' => 'all',
                'daterange' => date('Y-m-d', strtotime('-30 day')) . ' - ' . date('Y-m-d'),
                'affiliate_id' => $this->affiliate_id
            ],
            'loader' => '...',
        ];

        if ($this->affiliate_id && $user = get_userdata($this->affiliate_id)) {
            include salesloo_get_template('admin/affiliate-id.php');
        } else {
            include salesloo_get_template('admin/affiliate.php');
        }
        return;
    }

    /**
     * split_daterange
     *
     * @param  string $daterange
     * @param  bool $time
     * @return object
     */
    private function split_daterange($daterange, $time = false)
    {
        global $wpdb;

        if ($daterange) {
            $date = explode(' - ', $daterange);
            $date_start = date('Y-m-d', strtotime($date[0]));
            $date_end = isset($date[1]) ? date('Y-m-d', strtotime($date[1])) : date('Y-m-d', strtotime($date[0]));
        } else {
            $first_data = $wpdb->get_row("SELECT ID,visited_at FROM {$wpdb->prefix}salesloo_affiliate_click ORDER BY visited_at ASC");
            $date_start = $first_data->visited_at ? date('Y-m-d', strtotime($first_data->visited_at)) : '2000-01-01';
            $date_end = date('Y-m-d');
        }

        return (object)[
            'start' => $time ? date('Y-m-d 00:00:00', strtotime($date_start)) : $date_start,
            'end' => $time ? date('Y-m-d 23:59:59', strtotime($date_end)) : $date_end
        ];
    }

    public function visit_chart_monthly_query()
    {
        global $wpdb;

        [$daterange, $products, $affiliate_id] = $this->args;
        [$affiliate_click] = $this->table;

        $date = $this->split_daterange($daterange);

        $periode = new \DatePeriod(
            new \DateTime($date->start),
            new \DateInterval('P1M'),
            new \DateTime($date->end)
        );

        $query =
            "SELECT
                COUNT(
                    *
                ) AS click,
                COUNT(
                    DISTINCT ip
                ) AS uclick,
                DATE_FORMAT(visited_at, '%Y-%m') as date

            FROM $affiliate_click

            WHERE DATE(visited_at) BETWEEN '$date->start' AND '$date->end'

            AND product_id IN ($products)

            AND affiliate_id IN ($affiliate_id)

            GROUP BY DATE_FORMAT(visited_at, '%Y-%m')";

        $results = $wpdb->get_results($query);

        $data = [];
        foreach ($results as $result) {
            $data[$result->date] = $result;
        }

        $categories = [];
        $clicks = [];
        $uclicks = [];
        foreach ($periode as $key => $value) {
            $categories[] = $value->format('Y/m');

            $date_key = $value->format('Y-m');
            $click = 0;
            $uclick = 0;

            if (isset($data[$date_key])) {
                $click = $data[$date_key]->click ? intval($data[$date_key]->click) : $click;
                $uclick = $data[$date_key]->uclick ? intval($data[$date_key]->uclick) : $uclick;
            }

            $clicks[] = $click;
            $uclicks[] = $uclick;
        }

        return (object)[
            'click' => $clicks,
            'uclick' => $uclicks,
            'categories' => $categories
        ];
    }

    public function visit_chart_daily_query()
    {
        global $wpdb;

        [$daterange, $products, $affiliate_id] = $this->args;
        [$affiliate_click] = $this->table;

        $date = $this->split_daterange($daterange);

        $periode = new \DatePeriod(
            new \DateTime($date->start),
            new \DateInterval('P1D'),
            new \DateTime($date->end)
        );

        $query =
            "SELECT
                COUNT(
                    *
                ) AS click,
                COUNT(
                    DISTINCT ip
                ) AS uclick,
                DATE(visited_at) as date

            FROM $affiliate_click

            WHERE DATE(visited_at) BETWEEN '$date->start' AND '$date->end'
            
            AND product_id IN ($products)

            AND affiliate_id IN ($affiliate_id)

            GROUP BY DATE(visited_at)";

        $results = $wpdb->get_results($query);

        $data = [];
        foreach ($results as $result) {
            $data[$result->date] = $result;
        }

        $categories = [];
        $clicks = [];
        $uclicks = [];
        foreach ($periode as $key => $value) {
            $categories[] = $value->format('d/m/y');

            $date_key = $value->format('Y-m-d');
            $click = 0;
            $uclick = 0;

            if (isset($data[$date_key])) {
                $click = $data[$date_key]->click ? intval($data[$date_key]->click) : $click;
                $click = $data[$date_key]->uclick ? intval($data[$date_key]->uclick) : $uclick;
            }

            $clicks[] = $click;
            $uclicks[] = $uclick;
        }

        return (object)[
            'click' => $clicks,
            'uclick' => $clicks,
            'categories' => $categories
        ];
    }

    /**
     * hourly_query
     *
     * @return void
     */
    private function visit_chart_hourly_query()
    {
        global $wpdb;

        [$daterange, $products, $affiliate_id] = $this->args;
        [$affiliate_click] = $this->table;

        $date = $this->split_daterange($daterange, true);

        $periode = [];
        $startdate = $date->start;
        $enddate = date('Y-m-d 23:00:00', strtotime($date->end));
        $periode[] = $startdate;
        while ($startdate < $enddate) {
            $startdate = strtotime($startdate) + 3600;
            $startdate = date('Y-m-d H:i:s', $startdate);
            $periode[] = $startdate;
        }

        $query =
            "SELECT
                COUNT(
                    *
                ) AS click,
                COUNT(
                    DISTINCT ip
                ) AS uclick,
                DATE_FORMAT(visited_at, '%Y-%m-%d %H:00:00') as date

            FROM $affiliate_click

            WHERE DATE(visited_at) BETWEEN '$date->start' AND '$date->end'

            AND product_id IN ($products)

            AND affiliate_id IN ($affiliate_id)

            GROUP BY DATE_FORMAT(visited_at, '%Y-%m-%d %H:00:00')";

        $results = $wpdb->get_results($query);

        $data = [];
        foreach ($results as $result) {
            $data[$result->date] = $result;
        }

        $categories = [];
        $clicks = [];
        $uclicks = [];
        foreach ($periode as $key => $value) {
            $categories[] = date('y/m/d H:i', strtotime($value));

            $date_key = $value;
            $click = 0;
            $uclick = 0;

            if (isset($data[$date_key])) {
                $click = $data[$date_key]->click ? intval($data[$date_key]->click) : $click;
                $click = $data[$date_key]->uclick ? intval($data[$date_key]->uclick) : $uclick;
            }

            $clicks[] = $click;
            $uclicks[] = $uclick;
        }

        return (object)[
            'click' => $clicks,
            'uclick' => $uclicks,
            'categories' => $categories
        ];
    }

    public function ajax_get_chart_visits()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_get_chart_visits');

        $affiliate_id = isset($_GET['affiliate_id']) ? intval($_GET['affiliate_id']) : 0;

        $daterange     = isset($_GET['date']) ? sanitize_text_field($_GET['date']) : '';
        $products = isset($_GET['product_id']) ? $_GET['product_id'] : 'all';

        $invoice_status = array_keys(salesloo_get_invoice_statuses());
        $invoice_status = implode('\',\'', $invoice_status);

        if ($products == 'all' || empty($products)) {
            $products = "SELECT ID FROM {$wpdb->prefix}salesloo_product";
        } else {
            $products = is_array($products) ? implode('\',\'', array_map('sanitize_text_field', $products)) : sanitize_text_field($products);
            $products = "'$products'";
        }

        $this->table = [
            $wpdb->prefix . 'salesloo_affiliate_click',
        ];

        $this->args = [
            $daterange,
            $products,
            $affiliate_id
        ];

        $date = $this->split_daterange($daterange);

        $date1 = date_create($date->start);
        $date2 = date_create($date->end);
        $diff  = date_diff($date1, $date2);
        $month = intval($diff->format('%m'));

        if ($month > 3) {
            $results = $this->visit_chart_monthly_query();
        } else {
            $day = intval($diff->format('%a'));
            if ($day > 3) {
                $results = $this->visit_chart_daily_query();
            } else {
                $results = $this->visit_chart_hourly_query();
            }
        }

        $number = wp_parse_args($results->click, $results->uclick);
        $higher_number = max($number);

        $res = [
            'series' => [
                [
                    'name' => 'Click',
                    'type' => 'area',
                    'data' => $results->click
                ],
                [
                    'name' => 'Unique Click',
                    'type' => 'area',
                    'data' => $results->uclick
                ],
            ],
            'xaxis' => [
                'categories' => $results->categories,
                'title' => [
                    'text' => ''
                ]
            ],
            'maxnumber' => $higher_number
        ];

        wp_send_json($res);
    }

    public function ajax_get_stat_visits()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_get_stat_visits');

        $daterange     = isset($_GET['date']) ? sanitize_text_field($_GET['date']) : '';
        $products = isset($_GET['product_id']) ? $_GET['product_id'] : 'all';
        $affiliate_id = isset($_GET['affiliate_id']) ? intval($_GET['affiliate_id']) : 0;

        if ($products == 'all' || empty($products)) {
            $products = "SELECT ID FROM {$wpdb->prefix}salesloo_product";
        } else {
            $products = is_array($products) ? implode('\',\'', array_map('sanitize_text_field', $products)) : sanitize_text_field($products);
            $products = "'$products'";
        }

        $affiliate_click = $wpdb->prefix . 'salesloo_affiliate_click';

        $date = $this->split_daterange($daterange);

        $query =
            "SELECT
                COUNT(
                    *
                ) AS click,
                COUNT(
                    DISTINCT IP
                ) AS uclick,
                DATE(visited_at) as date

            FROM $affiliate_click

            WHERE DATE(visited_at) BETWEEN '$date->start' AND '$date->end'

            AND product_id IN ($products)
            
            AND affiliate_id IN ($affiliate_id)";

        $results = $wpdb->get_row($query);

        wp_send_json($results);
    }

    /**
     * ajax_get_stat
     *
     * @return void
     */
    public function ajax_get_stat_aff()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_get_stat_aff');

        $daterange     = isset($_GET['date']) ? sanitize_text_field($_GET['date']) : '';
        $products = isset($_GET['product_id']) ? $_GET['product_id'] : 'all';
        $affiliate_id = isset($_GET['affiliate_id']) ? intval($_GET['affiliate_id']) : 0;

        $commission = $wpdb->prefix . 'salesloo_commission';

        if ($products == 'all' || empty($products)) {
            $products = "SELECT ID FROM {$wpdb->prefix}salesloo_product";
        } else {
            $products = is_array($products) ? implode('\',\'', array_map('sanitize_text_field', $products)) : sanitize_text_field($products);
            $products = "'$products'";
        }

        $date = $this->split_daterange($daterange);

        $query =
            "SELECT
                COUNT(
                    CASE 
                    WHEN status IN ('pending','unpaid', 'paid', 'cancelled')
                    THEN ID ELSE NULL END
                ) AS leads,
                COUNT(
                    CASE 
                    WHEN status IN ('unpaid', 'paid')
                    THEN ID ELSE NULL END
                ) AS sales

            FROM (
                SELECT * FROM $commission
                
                WHERE DATE(created_at) BETWEEN '$date->start' AND '$date->end'
                
                AND product_id IN ($products)
                
                AND user_id IN ($affiliate_id)

                GROUP BY invoice_id
            ) commission";

        $result = $wpdb->get_row($query);

        if (intval($result->leads) == 0) {
            $conversion = intval($result->sales) * 100;
        } else {
            $conversion = intval($result->sales) / intval($result->leads) * 100;
        }

        $result->conversion = intval($result->sales) == 0 ? '0%' : round($conversion, 2) . '%';

        wp_send_json($result);
    }

    /**
     * ajax_get_stat
     *
     * @return void
     */
    public function ajax_get_stat_commission()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_get_stat_commission');

        $daterange    = isset($_GET['date']) ? sanitize_text_field($_GET['date']) : '';
        $products     = isset($_GET['product_id']) ? $_GET['product_id'] : 'all';
        $affiliate_id = isset($_GET['affiliate_id']) ? intval($_GET['affiliate_id']) : 0;

        $commission = $wpdb->prefix . 'salesloo_commission';

        if ($products == 'all' || empty($products)) {
            $products = "SELECT ID FROM {$wpdb->prefix}salesloo_product";
        } else {
            $products = is_array($products) ? implode('\',\'', array_map('sanitize_text_field', $products)) : sanitize_text_field($products);
            $products = "'$products'";
        }

        $date = $this->split_daterange($daterange);

        $query =
            "SELECT
                SUM(
                    CASE 
                    WHEN status IN ('unpaid', 'paid')
                    THEN amount ELSE 0 END
                ) AS total,
                SUM(
                    CASE 
                    WHEN status IN ('paid')
                    THEN amount ELSE 0 END
                ) AS paid,
                SUM(
                    CASE 
                    WHEN status IN ('unpaid')
                    THEN amount ELSE 0 END
                ) AS unpaid

            FROM $commission
            
            WHERE DATE(created_at) BETWEEN '$date->start' AND '$date->end'
            
            AND product_id IN ($products)
                
            AND user_id IN ($affiliate_id)";

        $result = $wpdb->get_row($query);
        $result->total = salesloo_convert_money($result->total);
        $result->unpaid = salesloo_convert_money($result->unpaid);
        $result->paid = salesloo_convert_money($result->paid);

        wp_send_json($result);
    }

    public function ajax_get_commissions()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_get_commissions');

        $per_page  = 5;
        $paged     = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
        $offset    = ($paged - 1) * $per_page;
        $affiliate_id = isset($_GET['affiliate_id']) ? intval($_GET['affiliate_id']) : 0;

        $commission = $wpdb->prefix . 'salesloo_commission';

        $query =
            "SELECT SQL_CALC_FOUND_ROWS *

            FROM $commission

            WHERE user_id = $affiliate_id

            ORDER BY ID DESC

            LIMIT %d OFFSET %d";

        $results = $wpdb->get_results($wpdb->prepare($query, $per_page, $offset));
        $found = $wpdb->get_var('SELECT FOUND_ROWS()');

        $items = [];
        foreach ($results as $item) {

            $status = $item->status;
            $status_bg = 'bg-blue-200 text-blue-500';

            if ($status == 'unpaid') {
                $status_bg = 'bg-blue-200 text-blue-500';
            }

            if ($status == 'paid') {
                $status_bg = 'bg-green-200 text-green-500';
            }

            if ($status == 'cancelled') {
                $status_bg = 'bg-gray-200 text-gray-500';
            }

            if ($status == 'pending') {
                $status_bg = 'bg-orange-200 text-orange-500';
            }

            $product = salesloo_get_product($item->product_id);
            $item->amount = salesloo_convert_money($item->amount);
            $item->product = $product->title;
            $item->status = (object)[
                'value' => ucfirst($status),
                'bg' => $status_bg
            ];
            $items[] = $item;
        }

        $data = [
            'items'    => $items,
            'total'    => $found,
            'paged'    => $paged,
            'pages'    => ceil($found / $per_page),
            'per_page' => $per_page,
        ];

        wp_send_json($data);
    }

    /**
     * ajax_get_affiliates
     *
     * @return void
     */
    public function ajax_get_affiliates()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_get_affiliates');

        $per_page  = 20;
        $paged     = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
        $offset    = ($paged - 1) * $per_page;
        $search    = isset($_GET['search']) ? sanitize_text_field($_GET['search']) : '';

        $user = $wpdb->users;


        if ($search) {
            $search = "WHERE user_login LIKE '%$search%' OR user_email LIKE '%$search%' OR display_name LIKE '%$search%' OR user_nicename LIKE '%$search%'";
        }

        $query =
            "SELECT SQL_CALC_FOUND_ROWS ID, user_registered

            FROM $wpdb->users

            $search

            ORDER BY ID ASC

            LIMIT %d OFFSET %d";

        $results = $wpdb->get_results($wpdb->prepare($query, $per_page, $offset));
        $found = $wpdb->get_var('SELECT FOUND_ROWS()');

        $items = [];
        foreach ($results as $item) {
            $user = get_userdata($item->ID);

            $item->name = salesloo_user_get_name($item->ID);

            $avatar = get_user_meta($item->ID, 'avatar', true);
            if (empty($avatar)) {
                $avatar = get_avatar_url($item->ID);
            }

            if (empty($avatar)) {
                $avatar = 'https://ui-avatars.com/api/?name=' . urlencode($item->name);
            }

            $status = get_user_meta($item->ID, 'salesloo_affiliate_status', true);

            if (empty($status)) {
                $status = 'active';
            }

            $status_bg = 'bg-blue-200 text-blue-500';
            if ($status == 'blocked') {
                $status_bg = 'bg-red-200 text-red-500';
            }

            if ($status == 'inactive') {
                $status_bg = 'bg-orange-200 text-orange-500';
            }

            $item->avatar = $avatar;
            $item->username = $user->user_login;
            $item->email = $user->user_email;
            $item->registered_at = $item->user_registered;
            $item->status = (object)[
                'value' => ucfirst($status),
                'bg' => $status_bg
            ];
            unset($item->user_registered);
            $item->link = admin_url('admin.php?page=salesloo-affiliate&affiliate_id=' . $item->ID);

            $items[] = $item;
        }

        $data = [
            'items'    => $items,
            'total'    => $found,
            'paged'    => $paged,
            'pages'    => ceil($found / $per_page),
            'per_page' => $per_page,
        ];

        wp_send_json($data);
    }

    public function ajax_cancel_commission()
    {
        global $wpdb;

        $this->admin_ajax->verify_nonce($_GET['nonce'], 'salesloo_cancel_commission');

        $input = file_get_contents("php://input");
        $data = json_decode($input, true);

        $commission_id = $data['id'] ? intval($data['id']) : 0;

        $commission = $wpdb->prefix . 'salesloo_commission';

        $r = $wpdb->update(
            $commission,
            ['status' => 'cancelled'],
            ['ID' => $commission_id]
        );

        wp_send_json([
            'status' => 'success',
            'message' => 'Commission has been cancelled',
        ]);
    }


    public function install_hooks()
    {
        add_action('wp_ajax_salesloo_get_affiliates', [$this, 'ajax_get_affiliates']);
        add_action('wp_ajax_salesloo_get_commissions', [$this, 'ajax_get_commissions']);
        add_action('wp_ajax_salesloo_get_chart_visits', [$this, 'ajax_get_chart_visits']);
        add_action('wp_ajax_salesloo_get_stat_visits', [$this, 'ajax_get_stat_visits']);
        add_action('wp_ajax_salesloo_get_stat_aff', [$this, 'ajax_get_stat_aff']);
        add_action('wp_ajax_salesloo_get_stat_commission', [$this, 'ajax_get_stat_commission']);
        add_action('wp_ajax_salesloo_cancel_commission', [$this, 'ajax_cancel_commission']);
    }
}
