<?php
/**
 * Chart data for the admin management dashboard.
 *
 * @package Maca_Menu_List
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Number of days in a range (inclusive).
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return int
 */
function maca_menulist_dashboard_range_day_count($date_from, $date_to) {
    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $start = maca_menulist_wp_date_to_timestamp($range['date_from']);
    $end = maca_menulist_wp_date_to_timestamp($range['date_to']);

    if ($start === false || $end === false || $end < $start) {
        return 1;
    }

    return (int) floor(($end - $start) / DAY_IN_SECONDS) + 1;
}

/**
 * Daily buckets for chart axes (one bar/point per day).
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<int, array{key: string, label: string}>
 */
function maca_menulist_dashboard_get_daily_buckets($date_from, $date_to) {
    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $start = maca_menulist_wp_date_to_timestamp($range['date_from']);
    $end = maca_menulist_wp_date_to_timestamp($range['date_to']);
    $buckets = array();

    if ($start === false || $end === false) {
        return $buckets;
    }

    for ($time = $start; $time <= $end; $time += DAY_IN_SECONDS) {
        $key = wp_date('Y-m-d', $time);
        $buckets[] = array(
            'key' => $key,
            'label' => wp_date('j M', $time),
        );
    }

    return $buckets;
}

/**
 * Weekly buckets when the selected range is longer than 31 days.
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<int, array{key: string, label: string, from: string, to: string}>
 */
function maca_menulist_dashboard_get_weekly_buckets($date_from, $date_to) {
    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $start = maca_menulist_wp_date_to_timestamp($range['date_from']);
    $end = maca_menulist_wp_date_to_timestamp($range['date_to']);
    $buckets = array();

    if ($start === false || $end === false) {
        return $buckets;
    }

    $cursor = $start;
    while ($cursor <= $end) {
        $week_end = min($cursor + (6 * DAY_IN_SECONDS), $end);
        $from_key = wp_date('Y-m-d', $cursor);
        $to_key = wp_date('Y-m-d', $week_end);

        $buckets[] = array(
            'key' => $from_key . '_' . $to_key,
            'label' => wp_date('j M', $cursor) . ' – ' . wp_date('j M', $week_end),
            'from' => $from_key,
            'to' => $to_key,
        );

        $cursor = $week_end + DAY_IN_SECONDS;
    }

    return $buckets;
}

/**
 * Choose daily or weekly buckets based on range length.
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array{buckets: array<int, array<string, string>>, weekly: bool}
 */
function maca_menulist_dashboard_get_chart_buckets($date_from, $date_to) {
    $weekly = maca_menulist_dashboard_range_day_count($date_from, $date_to) > 31;

    return array(
        'buckets' => $weekly
            ? maca_menulist_dashboard_get_weekly_buckets($date_from, $date_to)
            : maca_menulist_dashboard_get_daily_buckets($date_from, $date_to),
        'weekly' => $weekly,
    );
}

/**
 * Map daily SQL rows onto bucket values.
 *
 * @param array<int, array{key: string, label: string, from?: string, to?: string}> $buckets  Chart buckets.
 * @param array<string, float|int>                                                $daily   Y-m-d => value.
 * @param bool                                                                      $weekly  Weekly aggregation.
 * @return array<int, float>
 */
function maca_menulist_dashboard_aggregate_bucket_values($buckets, $daily, $weekly) {
    $values = array();

    foreach ($buckets as $bucket) {
        if (!$weekly) {
            $key = $bucket['key'];
            $values[] = isset($daily[ $key ]) ? (float) $daily[ $key ] : 0.0;
            continue;
        }

        $sum = 0.0;
        $from = maca_menulist_wp_date_to_timestamp((string) ($bucket['from'] ?? $bucket['key']));
        $to = maca_menulist_wp_date_to_timestamp((string) ($bucket['to'] ?? $bucket['key']));

        if ($from === false || $to === false) {
            $values[] = 0.0;
            continue;
        }

        for ($time = $from; $time <= $to; $time += DAY_IN_SECONDS) {
            $day_key = wp_date('Y-m-d', $time);
            if (isset($daily[ $day_key ])) {
                $sum += (float) $daily[ $day_key ];
            }
        }

        $values[] = $sum;
    }

    return $values;
}

/**
 * Orders per day in range.
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<string, int>
 */
function maca_menulist_dashboard_daily_order_counts($date_from, $date_to) {
    global $wpdb;

    if (!maca_menulist_is_dishes_mode() || !maca_menulist_table_order_enabled()) {
        return array();
    }

    maca_menulist_db_ensure_table_order_tables();

    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $table = maca_menulist_db_table_orders_table();

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT DATE(created_at) AS day_key, COUNT(*) AS total
            FROM $table
            WHERE created_at >= %s AND created_at <= %s
            GROUP BY DATE(created_at)",
            $range['date_from'] . ' 00:00:00',
            $range['date_to'] . ' 23:59:59'
        )
    );

    $map = array();
    foreach ($rows as $row) {
        $map[ (string) $row->day_key ] = (int) $row->total;
    }

    return $map;
}

/**
 * Paid revenue per day in range.
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<string, float>
 */
function maca_menulist_dashboard_daily_revenue($date_from, $date_to) {
    global $wpdb;

    if (!maca_menulist_is_dishes_mode() || !maca_menulist_table_order_enabled()) {
        return array();
    }

    maca_menulist_db_ensure_table_order_tables();

    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $table = maca_menulist_db_table_orders_table();

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT DATE(
                    CASE
                        WHEN payment_status = %s THEN COALESCE(paid_at, created_at)
                        ELSE status_updated_at
                    END
                ) AS day_key,
                COALESCE(SUM(COALESCE(payment_amount, 0) + COALESCE(tip_amount, 0)), 0) AS total
            FROM $table
            WHERE COALESCE(payment_amount, 0) > 0
            AND (
                (payment_status = %s AND (
                    (paid_at IS NOT NULL AND paid_at >= %s AND paid_at <= %s)
                    OR (paid_at IS NULL AND created_at >= %s AND created_at <= %s)
                ))
                OR (payment_status = %s AND status_updated_at >= %s AND status_updated_at <= %s)
            )
            GROUP BY day_key",
            'paid',
            'paid',
            $range['date_from'] . ' 00:00:00',
            $range['date_to'] . ' 23:59:59',
            $range['date_from'] . ' 00:00:00',
            $range['date_to'] . ' 23:59:59',
            'partial',
            $range['date_from'] . ' 00:00:00',
            $range['date_to'] . ' 23:59:59'
        )
    );

    $map = array();
    foreach ($rows as $row) {
        $map[ (string) $row->day_key ] = round((float) $row->total, 2);
    }

    return $map;
}

/**
 * Dish clicks per day in range.
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<string, int>
 */
function maca_menulist_dashboard_daily_dish_clicks($date_from, $date_to) {
    global $wpdb;

    if (!maca_menulist_is_dishes_mode()) {
        return array();
    }

    maca_menulist_db_ensure_dish_views_table();

    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $table = maca_menulist_db_dish_views_table();

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT DATE(created_at) AS day_key, COUNT(*) AS total
            FROM $table
            WHERE created_at >= %s AND created_at <= %s
            GROUP BY DATE(created_at)",
            $range['date_from'] . ' 00:00:00',
            $range['date_to'] . ' 23:59:59'
        )
    );

    $map = array();
    foreach ($rows as $row) {
        $map[ (string) $row->day_key ] = (int) $row->total;
    }

    return $map;
}

/**
 * Bookings per day in range (by booking date).
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<string, int>
 */
function maca_menulist_dashboard_daily_bookings($date_from, $date_to) {
    global $wpdb;

    if (!maca_menulist_table_booking_enabled()) {
        return array();
    }

    maca_menulist_db_ensure_table_booking_tables();

    $range = maca_menulist_normalize_stats_date_range($date_from, $date_to);
    $table = maca_menulist_db_bookings_table();

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT booking_date AS day_key, COUNT(*) AS total
            FROM $table
            WHERE booking_date >= %s AND booking_date <= %s
            GROUP BY booking_date",
            $range['date_from'],
            $range['date_to']
        )
    );

    $map = array();
    foreach ($rows as $row) {
        $map[ (string) $row->day_key ] = (int) $row->total;
    }

    return $map;
}

/**
 * Build Chart.js-ready configs for the dashboard.
 *
 * @param string $date_from Y-m-d.
 * @param string $date_to   Y-m-d.
 * @return array<int, array<string, mixed>>
 */
function maca_menulist_get_dashboard_charts($date_from, $date_to) {
    $bucket_info = maca_menulist_dashboard_get_chart_buckets($date_from, $date_to);
    $buckets = $bucket_info['buckets'];
    $weekly = $bucket_info['weekly'];

    if (empty($buckets)) {
        return array();
    }

    $labels = array();
    foreach ($buckets as $bucket) {
        $labels[] = $bucket['label'];
    }

    $charts = array();

    if (maca_menulist_is_dishes_mode() && maca_menulist_table_order_enabled()) {
        $orders_daily = maca_menulist_dashboard_daily_order_counts($date_from, $date_to);
        $revenue_daily = maca_menulist_dashboard_daily_revenue($date_from, $date_to);
        $orders_values = maca_menulist_dashboard_aggregate_bucket_values($buckets, $orders_daily, $weekly);
        $revenue_values = maca_menulist_dashboard_aggregate_bucket_values($buckets, $revenue_daily, $weekly);

        if (array_sum($orders_values) > 0 || array_sum($revenue_values) > 0) {
            $charts[] = array(
                'id' => 'orders-revenue',
                'kind' => 'mixed',
                'title' => $weekly
                    ? __('Ordrar och intäkter per vecka', 'maca-restu-pro')
                    : __('Ordrar och intäkter per dag', 'maca-restu-pro'),
                'labels' => $labels,
                'datasets' => array(
                    array(
                        'key' => 'orders',
                        'label' => __('Ordrar', 'maca-restu-pro'),
                        'type' => 'bar',
                        'data' => $orders_values,
                        'color' => '#2271b1',
                        'yAxisID' => 'y',
                    ),
                    array(
                        'key' => 'revenue',
                        'label' => __('Intäkter', 'maca-restu-pro'),
                        'type' => 'line',
                        'data' => $revenue_values,
                        'color' => '#00a32a',
                        'yAxisID' => 'y1',
                        'format' => 'currency',
                    ),
                ),
            );
        }

        $period_args = array(
            'date_from' => maca_menulist_normalize_stats_date_range($date_from, $date_to)['date_from'],
            'date_to' => maca_menulist_normalize_stats_date_range($date_from, $date_to)['date_to'],
        );
        $payment_summary = maca_menulist_get_payment_history_summary($period_args);
        $paid = (int) $payment_summary['paid'];
        $pending = (int) $payment_summary['pending'];
        $unpaid = (int) $payment_summary['unpaid'];

        if ($paid + $pending + $unpaid > 0) {
            $charts[] = array(
                'id' => 'payment-status',
                'kind' => 'doughnut',
                'title' => __('Betalningsstatus i perioden', 'maca-restu-pro'),
                'labels' => array(
                    __('Betald', 'maca-restu-pro'),
                    __('Väntande', 'maca-restu-pro'),
                    __('Obetald', 'maca-restu-pro'),
                ),
                'data' => array($paid, $pending, $unpaid),
                'colors' => array('#00a32a', '#dba617', '#d63638'),
            );
        }
    }

    if (maca_menulist_is_dishes_mode()) {
        $clicks_daily = maca_menulist_dashboard_daily_dish_clicks($date_from, $date_to);
        $clicks_values = maca_menulist_dashboard_aggregate_bucket_values($buckets, $clicks_daily, $weekly);

        if (array_sum($clicks_values) > 0) {
            $charts[] = array(
                'id' => 'dish-clicks',
                'kind' => 'line',
                'title' => $weekly
                    ? __('Rättklick per vecka', 'maca-restu-pro')
                    : __('Rättklick per dag', 'maca-restu-pro'),
                'labels' => $labels,
                'datasets' => array(
                    array(
                        'key' => 'clicks',
                        'label' => __('Klick', 'maca-restu-pro'),
                        'type' => 'line',
                        'data' => $clicks_values,
                        'color' => '#dba617',
                        'fill' => true,
                    ),
                ),
            );
        }

        $top_dishes = maca_menulist_db_get_top_dishes_by_clicks($date_from, $date_to, 5);
        if (!empty($top_dishes)) {
            $dish_labels = array();
            $dish_values = array();
            foreach (array_reverse($top_dishes) as $dish) {
                $title = $dish['title'];
                if (function_exists('mb_strlen') && mb_strlen($title) > 28) {
                    $title = mb_substr($title, 0, 25) . '…';
                } elseif (strlen($title) > 28) {
                    $title = substr($title, 0, 25) . '…';
                }
                $dish_labels[] = $title;
                $dish_values[] = (int) $dish['clicks'];
            }

            $charts[] = array(
                'id' => 'top-dishes',
                'kind' => 'bar',
                'title' => __('Topprätter (klick)', 'maca-restu-pro'),
                'labels' => $dish_labels,
                'datasets' => array(
                    array(
                        'key' => 'clicks',
                        'label' => __('Klick', 'maca-restu-pro'),
                        'type' => 'bar',
                        'data' => $dish_values,
                        'color' => '#2271b1',
                        'horizontal' => true,
                    ),
                ),
            );
        }
    }

    if (maca_menulist_table_booking_enabled()) {
        $bookings_daily = maca_menulist_dashboard_daily_bookings($date_from, $date_to);
        $booking_values = maca_menulist_dashboard_aggregate_bucket_values($buckets, $bookings_daily, $weekly);

        if (array_sum($booking_values) > 0) {
            $charts[] = array(
                'id' => 'bookings',
                'kind' => 'bar',
                'title' => $weekly
                    ? __('Bokningar per vecka', 'maca-restu-pro')
                    : __('Bokningar per dag', 'maca-restu-pro'),
                'labels' => $labels,
                'datasets' => array(
                    array(
                        'key' => 'bookings',
                        'label' => __('Bokningar', 'maca-restu-pro'),
                        'type' => 'bar',
                        'data' => $booking_values,
                        'color' => '#8c5cd6',
                    ),
                ),
            );
        }
    }

    return $charts;
}
