<?php

namespace PageVICO\API;

defined( 'ABSPATH' ) || exit;
class RouteRegistrar {
    public static function init() {
        add_action( 'rest_api_init', array(__CLASS__, 'registerRoutes') );
    }

    public static function registerRoutes() {
        register_rest_route( 'pagevico/v1', '/track', array(
            'methods'             => 'POST',
            'callback'            => array(__CLASS__, 'handleTrack'),
            'permission_callback' => '__return_true',
        ) );
        register_rest_route( 'pagevico/v1', '/realtime', array(
            'methods'             => 'GET',
            'callback'            => array(__CLASS__, 'getRealtimeVisitors'),
            'permission_callback' => function () {
                return current_user_can( 'manage_options' ) && check_ajax_referer( 'wp_rest', '_wpnonce', false );
            },
        ) );
        // Add new endpoint for Geo Database update
        register_rest_route( 'pagevico/v1', '/update-geo-db', array(
            'methods'             => 'POST',
            'callback'            => array(__CLASS__, 'handleGeoDbUpdate'),
            'permission_callback' => function () {
                return current_user_can( 'manage_options' );
            },
        ) );
    }

    public static function handleTrack( $request ) {
        // Check initial conditions
        if ( !\PageVICO\Tracking\TrackingConditions::shouldTrack() ) {
            return new \WP_REST_Response(array(
                'success' => false,
                'message' => 'Tracking disabled based on current settings',
            ), 403);
        }
        global $wpdb;
        $data = $request->get_json_params();
        // Validate required data
        if ( empty( $data['page_url'] ) ) {
            return new \WP_REST_Response(array(
                'success' => false,
                'message' => 'Invalid data: page_url is required',
            ), 400);
        }
        // Generate a session ID based on IP address and user agent
        $ip_address = \PageVICO\Sessions\SessionManager::getClientIP();
        $ua = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) );
        // Define a rolling 30-minute session block
        $session_timeout = 30 * 60;
        // 1800 seconds
        $current_block = floor( time() / $session_timeout );
        // Optional: Add entropy using NONCE_SALT for uniqueness per install
        $session_id = hash( 'sha256', $ip_address . $ua . $current_block . NONCE_SALT );
        $page_url = esc_url_raw( $data['page_url'] );
        $referrer = esc_url_raw( $data['referrer'] ?? '' );
        // Get post type and ID from URL
        $post_id = url_to_postid( $page_url );
        $post_type = 'unknown';
        if ( $post_id ) {
            $post = get_post( $post_id );
            if ( $post ) {
                $post_type = $post->post_type;
                // Check if this post type is allowed
                $allowed_post_types = (array) get_option( 'PageVICO_post_types', array('post', 'page') );
                if ( !empty( $allowed_post_types ) && !in_array( $post_type, $allowed_post_types, true ) ) {
                    return new \WP_REST_Response(array(
                        'success' => false,
                        'message' => 'Post type not allowed for tracking',
                    ), 403);
                }
                // Check if this specific post is blocked
                $blocked_posts = (array) get_option( 'PageVICO_block_posts', array() );
                if ( !empty( $blocked_posts ) && in_array( $post_id, $blocked_posts, true ) ) {
                    return new \WP_REST_Response(array(
                        'success' => false,
                        'message' => 'Post is blocked from tracking',
                    ), 403);
                }
                // Check if this post is excluded from tracking
                $excluded_posts = (array) get_option( 'PageVICO_exclude_posts', array() );
                if ( !empty( $excluded_posts ) && in_array( $post_id, $excluded_posts, true ) ) {
                    return new \WP_REST_Response(array(
                        'success' => false,
                        'message' => 'Post is excluded from tracking',
                    ), 403);
                }
            }
        }
        // Try to update existing session first
        $session_updated = \PageVICO\Sessions\SessionManager::updateSessionLastSeen( $session_id, $data );
        // If update failed (session doesn't exist or is inactive), create new session
        if ( !$session_updated ) {
            $session_created = \PageVICO\Sessions\SessionManager::createSession( $session_id, $data );
            if ( !$session_created ) {
                return new \WP_REST_Response(array(
                    'success' => false,
                    'message' => 'Failed to create session',
                ), 500);
            }
        }
        // Insert page view
        $result = $wpdb->insert( PageVICO_TABLE_PAGEVIEWS, array(
            'session_id' => $session_id,
            'page_url'   => parse_url( $page_url, PHP_URL_PATH ),
            'post_type'  => $post_type,
            'post_id'    => ( $post_id ?: null ),
            'referrer'   => $referrer,
            'created_at' => current_time( 'mysql' ),
        ), array(
            '%s',
            '%s',
            '%s',
            '%d',
            '%s',
            '%s'
        ) );
        if ( $result === false ) {
            return new \WP_REST_Response(array(
                'success' => false,
                'message' => 'Database error',
            ), 500);
        }
        return new \WP_REST_Response(array(
            'success'    => true,
            'session_id' => $session_id,
        ), 200);
    }

    public static function getRealtimeVisitors( $request ) {
        global $wpdb;
        $threshold = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );
        // Local time
        $time_range = $request->get_param( 'time_range' );
        $is_historical = $request->get_param( 'historical' ) === 'true';
        // If historical data is requested, get data for the last 10 minutes
        if ( $is_historical ) {
            $start_time = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) - 600 );
            // 10 minutes ago
            $end_time = $threshold;
            // Get historical data points (one per minute for the last 10 minutes)
            $historical_data = array();
            for ($i = 0; $i < 10; $i++) {
                $point_time = date( 'Y-m-d H:i:s', strtotime( $start_time ) + $i * 60 );
                $next_point = date( 'Y-m-d H:i:s', strtotime( $point_time ) + 60 );
                // Count visitors for this minute
                $sql = $wpdb->prepare( "SELECT COUNT(DISTINCT session_id) FROM " . PageVICO_TABLE_SESSIONS . " \n\t\t\t\t\tWHERE last_seen >= %s AND last_seen < %s AND is_bot = 0 AND is_active = 1", $point_time, $next_point );
                $visitors = (int) $wpdb->get_var( $sql );
                // Count sessions for this minute
                $sql = $wpdb->prepare( "SELECT COUNT(*) FROM " . PageVICO_TABLE_PAGEVIEWS . " pv\n\t\t\t\t\tJOIN " . PageVICO_TABLE_SESSIONS . " s ON pv.session_id = s.session_id\n\t\t\t\t\tWHERE pv.created_at >= %s AND pv.created_at < %s AND s.is_active = 1", $point_time, $next_point );
                $sessions = (int) $wpdb->get_var( $sql );
                $historical_data[] = array(
                    'timestamp' => $point_time,
                    'visitors'  => $visitors,
                    'sessions'  => $sessions,
                );
            }
            return new \WP_REST_Response(array(
                'success'         => true,
                'historical_data' => $historical_data,
                'timestamp'       => $threshold,
            ), 200);
        }
        // For real-time updates, use the 5-minute window as before
        $threshold_time = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) - 300 );
        // Count active visitors (unique session IDs)
        $sql = $wpdb->prepare( "SELECT COUNT(DISTINCT session_id) FROM " . PageVICO_TABLE_SESSIONS . " \n\t\t\tWHERE last_seen >= %s AND is_bot = 0 AND is_active = 1", $threshold_time );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Safe prepared query, no caching required
        $active_visitors = (int) $wpdb->get_var( $sql );
        // Count active sessions (pageviews in the last 5 minutes)
        $sql = $wpdb->prepare( "SELECT COUNT(*) FROM " . PageVICO_TABLE_PAGEVIEWS . " pv\n\t\t\tJOIN " . PageVICO_TABLE_SESSIONS . " s ON pv.session_id = s.session_id\n\t\t\tWHERE pv.created_at >= %s AND s.is_active = 1", $threshold_time );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Safe prepared query, no caching required
        $active_sessions = (int) $wpdb->get_var( $sql );
        // Get top active countries
        $sql = $wpdb->prepare( "SELECT country, COUNT(*) as count \n\t\t\tFROM " . PageVICO_TABLE_SESSIONS . " \n\t\t\tWHERE last_seen >= %s AND is_bot = 0 AND is_active = 1\n\t\t\tGROUP BY country\n\t\t\tORDER BY count DESC\n\t\t\tLIMIT 5", $threshold_time );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Safe prepared query, no caching required
        $top_countries = $wpdb->get_results( $sql, ARRAY_A );
        // Get device breakdown
        $sql = $wpdb->prepare( "SELECT device_type, COUNT(*) as count \n\t\t\tFROM " . PageVICO_TABLE_SESSIONS . " \n\t\t\tWHERE last_seen >= %s AND is_bot = 0 AND is_active = 1\n\t\t\tGROUP BY device_type", $threshold_time );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- Safe prepared query, no caching required
        $devices = $wpdb->get_results( $sql, ARRAY_A );
        return new \WP_REST_Response(array(
            'success'         => true,
            'active_visitors' => $active_visitors,
            'active_sessions' => $active_sessions,
            'top_countries'   => $top_countries,
            'devices'         => $devices,
            'timestamp'       => $threshold,
        ), 200);
    }

    // Add new handler method
    public static function handleGeoDbUpdate() {
        if ( !class_exists( 'PageVICO\\Geo\\GeoService' ) ) {
            return new \WP_REST_Response(array(
                'success' => false,
                'message' => 'GeoService class not found',
            ), 500);
        }
        $success = \PageVICO\Geo\GeoService::downloadDatabase();
        if ( $success ) {
            update_option( 'PageVICO_geo_db_last_updated', time() );
            return new \WP_REST_Response(array(
                'success'      => true,
                'message'      => __( 'Geo Database updated successfully', 'page-visit-counter-analytics' ),
                'last_updated' => date_i18n( get_option( 'date_format' ), time() ),
            ), 200);
        }
        return new \WP_REST_Response(array(
            'success' => false,
            'message' => __( 'Failed to update Geo Database', 'page-visit-counter-analytics' ),
        ), 500);
    }

}
