<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * REST API: /vlens/v1/stats/*
 * Serves analytics data for the admin dashboard.
 */
class VLENS_REST_Stats {

    public function register_routes() {
        $admin_perm = function () {
            return current_user_can( 'manage_options' );
        };

        register_rest_route( 'vlens/v1', '/stats/summary', [
            'methods'  => 'GET', 'callback' => [ $this, 'summary' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/chart', [
            'methods'  => 'GET', 'callback' => [ $this, 'chart' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/countries', [
            'methods'  => 'GET', 'callback' => [ $this, 'countries' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/browsers', [
            'methods'  => 'GET', 'callback' => [ $this, 'browsers' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/platforms', [
            'methods'  => 'GET', 'callback' => [ $this, 'platforms' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/referrers', [
            'methods'  => 'GET', 'callback' => [ $this, 'referrers' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/pages', [
            'methods'  => 'GET', 'callback' => [ $this, 'pages' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/devices', [
            'methods'  => 'GET', 'callback' => [ $this, 'devices' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/recent', [
            'methods'  => 'GET', 'callback' => [ $this, 'recent' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/search_engines', [
            'methods'  => 'GET', 'callback' => [ $this, 'search_engines' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/performance', [
            'methods'  => 'GET', 'callback' => [ $this, 'performance' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/traffic_summary', [
            'methods'  => 'GET', 'callback' => [ $this, 'traffic_summary' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/most_active', [
            'methods'  => 'GET', 'callback' => [ $this, 'most_active' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/online_now', [
            'methods'  => 'GET', 'callback' => [ $this, 'online_now' ], 'permission_callback' => $admin_perm,
        ] );
        register_rest_route( 'vlens/v1', '/stats/chart_weekly', [
            'methods'  => 'GET', 'callback' => [ $this, 'chart_weekly' ], 'permission_callback' => $admin_perm,
        ] );
    }

    private function get_range( WP_REST_Request $r ): int {
        $range = absint( $r->get_param( 'range' ) ?: 30 );
        return in_array( $range, [ 7, 30, 90, 365 ], true ) ? $range : 30;
    }

    public function summary( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $td = VLENS_Helpers::table( 'daily_summary' );
        $to = VLENS_Helpers::table( 'online' );

        $today = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE date = CURDATE()", $td ), ARRAY_A );
        $period = $wpdb->get_row( $wpdb->prepare(
            "SELECT SUM(visitors) AS v, SUM(page_views) AS pv FROM %i WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)", $td, $range
        ), ARRAY_A );
        $online = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE last_seen >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)", $to ) );

        return [
            'today_visitors'  => (int) ( $today['visitors'] ?? 0 ),
            'today_views'     => (int) ( $today['page_views'] ?? 0 ),
            'period_visitors' => (int) ( $period['v'] ?? 0 ),
            'period_views'    => (int) ( $period['pv'] ?? 0 ),
            'online'          => $online,
        ];
    }

    public function chart( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'daily_summary' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT date, visitors, page_views FROM %i WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY) ORDER BY date ASC", $t, $range
        ), ARRAY_A );
    }

    public function countries( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'countries' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT country_code, country_name, SUM(visitors) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY country_code, country_name ORDER BY v DESC LIMIT 10", $t, $range
        ), ARRAY_A );
    }

    public function browsers( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'browsers' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT browser, SUM(visitors) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY browser ORDER BY v DESC LIMIT 8", $t, $range
        ), ARRAY_A );
    }

    public function platforms( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'platforms' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT platform, SUM(visitors) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY platform ORDER BY v DESC LIMIT 8", $t, $range
        ), ARRAY_A );
    }

    public function referrers( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'referrers' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT host, SUM(visits) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY host ORDER BY v DESC LIMIT 10", $t, $range
        ), ARRAY_A );
    }

    public function pages( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'visits' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT page_uri, page_title, COUNT(*) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY page_uri, page_title ORDER BY v DESC LIMIT 10", $t, $range
        ), ARRAY_A );
    }

    public function devices( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'visitors' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT device_type, COUNT(*) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY device_type ORDER BY v DESC", $t, $range
        ), ARRAY_A );
    }

    public function search_engines( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'search_engines' );
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT engine, SUM(visits) AS v FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY engine ORDER BY v DESC LIMIT 6", $t, $range
        ), ARRAY_A );
    }

    public function performance( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t = VLENS_Helpers::table( 'visits' );

        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT ROUND(AVG(load_time_ms)) AS avg_ms, ROUND(MIN(load_time_ms)) AS min_ms, ROUND(MAX(load_time_ms)) AS max_ms, COUNT(*) AS samples
             FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY) AND load_time_ms IS NOT NULL AND load_time_ms > 0",
            $t, $range
        ), ARRAY_A );

        $today_row = $wpdb->get_row( $wpdb->prepare(
            "SELECT ROUND(AVG(load_time_ms)) AS avg_ms, COUNT(*) AS samples
             FROM %i
             WHERE date = CURDATE() AND load_time_ms IS NOT NULL AND load_time_ms > 0",
            $t
        ), ARRAY_A );

        $daily = $wpdb->get_results( $wpdb->prepare(
            "SELECT date, ROUND(AVG(load_time_ms)) AS avg_ms, COUNT(*) AS samples
             FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY) AND load_time_ms IS NOT NULL AND load_time_ms > 0
             GROUP BY date ORDER BY date ASC",
            $t, $range
        ), ARRAY_A );

        return [
            'period_avg_ms' => (int) ( $row['avg_ms'] ?? 0 ),
            'period_min_ms' => (int) ( $row['min_ms'] ?? 0 ),
            'period_max_ms' => (int) ( $row['max_ms'] ?? 0 ),
            'period_samples'=> (int) ( $row['samples'] ?? 0 ),
            'today_avg_ms'  => (int) ( $today_row['avg_ms'] ?? 0 ),
            'today_samples' => (int) ( $today_row['samples'] ?? 0 ),
            'daily'         => is_array( $daily ) ? $daily : [],
        ];
    }

    public function traffic_summary( WP_REST_Request $r ) {
        global $wpdb;
        $t = VLENS_Helpers::table( 'daily_summary' );

        $cache_key = 'vlens_traffic_summary';
        $cached    = get_transient( $cache_key );
        if ( $cached !== false ) return $cached;

        $sel = 'SELECT COALESCE(SUM(visitors),0) AS visitors, COALESCE(SUM(page_views),0) AS page_views FROM %i';

        $result = [
            'today'      => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date = CURDATE()", $t ), ARRAY_A ),
            'yesterday'  => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date = DATE_SUB(CURDATE(), INTERVAL 1 DAY)", $t ), ARRAY_A ),
            'this_week'  => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE YEARWEEK(date,1) = YEARWEEK(CURDATE(),1)", $t ), ARRAY_A ),
            'last_week'  => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE YEARWEEK(date,1) = YEARWEEK(DATE_SUB(CURDATE(),INTERVAL 7 DAY),1)", $t ), ARRAY_A ),
            'this_month' => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date >= DATE_FORMAT(CURDATE(),'%%Y-%%m-01') AND date <= CURDATE()", $t ), ARRAY_A ),
            'last_month' => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date >= DATE_FORMAT(DATE_SUB(CURDATE(),INTERVAL 1 MONTH),'%%Y-%%m-01') AND date < DATE_FORMAT(CURDATE(),'%%Y-%%m-01')", $t ), ARRAY_A ),
            'last_7'     => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)", $t ), ARRAY_A ),
            'last_30'    => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)", $t ), ARRAY_A ),
            'last_90'    => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date >= DATE_SUB(CURDATE(), INTERVAL 90 DAY)", $t ), ARRAY_A ),
            'this_year'  => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE date >= DATE_FORMAT(CURDATE(),'%%Y-01-01')", $t ), ARRAY_A ),
            'total'      => $wpdb->get_row( $wpdb->prepare( "{$sel} WHERE 1=1", $t ), ARRAY_A ),
        ];

        set_transient( $cache_key, $result, 5 * MINUTE_IN_SECONDS );
        return $result;
    }

    public function most_active( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $tv    = VLENS_Helpers::table( 'visitors' );
        $tt    = VLENS_Helpers::table( 'visits' );

        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT vi.id, vi.ip_raw, vi.country_code, vi.country_name, vi.browser,
                    vi.device_type, vi.created_at,
                    COUNT(vt.id) AS views,
                    MAX(vt.created_at) AS last_seen,
                    (SELECT vt2.page_uri FROM %i vt2
                     WHERE vt2.visitor_id = vi.id ORDER BY vt2.id ASC LIMIT 1) AS entry_page,
                    (SELECT vt3.page_uri FROM %i vt3
                     WHERE vt3.visitor_id = vi.id ORDER BY vt3.id DESC LIMIT 1) AS exit_page,
                    (SELECT vt4.referrer_host FROM %i vt4
                     WHERE vt4.visitor_id = vi.id ORDER BY vt4.id ASC LIMIT 1) AS referrer
             FROM %i vi
             LEFT JOIN %i vt ON vt.visitor_id = vi.id
             WHERE vi.date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY vi.id
             ORDER BY views DESC
             LIMIT 10",
            $tt, $tt, $tt, $tv, $tt, $range
        ), ARRAY_A );

        return is_array( $rows ) ? $rows : [];
    }

    public function online_now( WP_REST_Request $r ) {
        global $wpdb;
        $to = VLENS_Helpers::table( 'online' );
        $tv = VLENS_Helpers::table( 'visitors' );
        $tt = VLENS_Helpers::table( 'visits' );

        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT o.ip_raw, o.last_seen, o.page_uri,
                    TIMESTAMPDIFF(SECOND, o.last_seen, NOW()) AS seconds_ago,
                    vi.country_code, vi.country_name, vi.browser, vi.device_type
             FROM %i o
             LEFT JOIN %i vi ON vi.ip_raw = o.ip_raw
               AND vi.id = (SELECT MAX(v2.id) FROM %i v2 WHERE v2.ip_raw = o.ip_raw)
             WHERE o.last_seen >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)
             ORDER BY o.last_seen DESC
             LIMIT 20",
            $to, $tv, $tv
        ), ARRAY_A );

        return is_array( $rows ) ? $rows : [];
    }

    public function chart_weekly( WP_REST_Request $r ) {
        global $wpdb;
        $range = $this->get_range( $r );
        $t     = VLENS_Helpers::table( 'daily_summary' );

        return $wpdb->get_results( $wpdb->prepare(
            "SELECT YEARWEEK(date,1) AS yw,
                    DATE_FORMAT(MIN(date),'%%Y-%%m-%%d') AS week_start,
                    SUM(visitors) AS visitors,
                    SUM(page_views) AS page_views
             FROM %i
             WHERE date >= DATE_SUB(CURDATE(), INTERVAL %d DAY)
             GROUP BY yw
             ORDER BY yw ASC",
            $t, $range
        ), ARRAY_A );
    }

    public function recent( WP_REST_Request $r ) {
        global $wpdb;
        $tv = VLENS_Helpers::table( 'visitors' );
        $tt = VLENS_Helpers::table( 'visits' );
        $ts = VLENS_Helpers::table( 'sessions' );
        $to = VLENS_Helpers::table( 'online' );

        $visitors = $wpdb->get_results( $wpdb->prepare(
            "SELECT vi.id AS visitor_id, vi.created_at, vi.ip_raw,
                    vi.country_code, vi.country_name, vi.browser, vi.platform, vi.device_type,
                    vt.page_uri, vt.page_title, vt.referrer_type,
                    s.id AS session_id,
                    vi.wp_user_id,
                    u.display_name AS wp_display_name
             FROM %i vi
             INNER JOIN (
                 SELECT ip_raw, MAX(id) AS max_id
                 FROM %i
                 WHERE date >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)
                 GROUP BY ip_raw
             ) latest ON latest.max_id = vi.id
             LEFT JOIN %i vt ON vt.visitor_id = vi.id
               AND vt.id = (SELECT MAX(vt2.id) FROM %i vt2 WHERE vt2.visitor_id = vi.id)
             LEFT JOIN %i s ON s.visitor_id = vi.id
               AND s.id = (SELECT MAX(s2.id) FROM %i s2 WHERE s2.visitor_id = vi.id)
             LEFT JOIN %i u ON u.ID = vi.wp_user_id
             ORDER BY vi.created_at DESC LIMIT 20",
            $tv, $tv, $tt, $tt, $ts, $ts, $wpdb->users
        ), ARRAY_A );

        $online_ips = $wpdb->get_col( $wpdb->prepare(
            "SELECT ip_raw FROM %i WHERE ip_raw IS NOT NULL AND ip_raw != ''
             AND last_seen >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)",
            $to
        ) );

        return [
            'visitors'   => $visitors,
            'online_ips' => $online_ips,
        ];
    }
}
