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

class ShippingGuard_Analytics_API {
    public function init() {
        add_action( 'rest_api_init', array( $this, 'register_routes' ) );
    }

    public function register_routes() {
        register_rest_route( 'shippingguard/v1', '/analytics', array(
            'methods'             => 'GET',
            'callback'            => array( $this, 'get_analytics_data' ),
            'permission_callback' => function() {
                return current_user_can( 'manage_options' );
            },
        ) );
    }

    public function get_analytics_data( $request ) {
        global $wpdb;
        $start_date = $request->get_param( 'start_date' );
        $end_date   = $request->get_param( 'end_date' );

        if ( ! $start_date ) $start_date = gmdate( 'Y-m-d', strtotime( '-30 days' ) );
        if ( ! $end_date ) $end_date = gmdate( 'Y-m-d' );

        // 1. Fetch Orders with Protection using WooCommerce CRUD API (HPOS Compatible)
        $order_args = array(
            'limit'        => 500,
            'date_created' => $start_date . ' 00:00:00...' . $end_date . ' 23:59:59',
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Filtering by protection meta is required.
            'meta_key'     => '_shipping_protection_enabled',
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
            'meta_value'   => 'yes',
            'status'       => array_diff( array_keys( wc_get_order_statuses() ), array( 'wc-cancelled', 'wc-failed' ) ),
        );

        $protected_orders = wc_get_orders( $order_args );
        
        $total_protected_orders = count( $protected_orders );
        $total_revenue = 0;
        $daily_revenue = array();
        $product_counts = array();

        foreach ( $protected_orders as $order ) {
            $fee = (float) $order->get_meta( '_shipping_protection_fee' );
            $total_revenue += $fee;

            $date = $order->get_date_created()->date( 'Y-m-d' );
            $daily_revenue[ $date ] = ( $daily_revenue[ $date ] ?? 0 ) + $fee;

            // Top Protected Products logic
            foreach ( $order->get_items() as $item ) {
                if ( ! is_a( $item, 'WC_Order_Item_Product' ) ) continue;
                $product_id = $item->get_product_id();
                $product_name = $item->get_name();
                if ( ! isset( $product_counts[ $product_id ] ) ) {
                    $product_counts[ $product_id ] = array( 'name' => $product_name, 'count' => 0 );
                }
                $product_counts[ $product_id ]['count'] += $item->get_quantity();
            }
        }

        // Sort Top Products
        uasort( $product_counts, function( $a, $b ) { return $b['count'] - $a['count']; } );
        $top_products = array_slice( $product_counts, 0, 5, true );

        // 2. Fetch Claims within date range
        $claims_table = esc_sql( $wpdb->prefix . 'shippingguard_claims' ); // Table name — cannot use placeholder, esc_sql() is the correct sanitization.
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Needed for complex timeframe reporting.
        $claims = $wpdb->get_results( $wpdb->prepare(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name is hardcoded prefix + fixed string, safely escaped with esc_sql().
            "SELECT * FROM {$claims_table} WHERE created_at >= %s AND created_at <= %s",
            $start_date . ' 00:00:00',
            $end_date . ' 23:59:59'
        ) );
        $total_claims = count( $claims );

        $daily_claims = array();
        foreach ( $claims as $claim ) {
            $date = gmdate( 'Y-m-d', strtotime( $claim->created_at ) );
            $daily_claims[ $date ] = ( $daily_claims[ $date ] ?? 0 ) + 1;
        }

        // 3. Logistics Fees & Eco Deliveries (Real calculation)
        $logistics_revenue = 0;
        $eco_orders_count = 0;
        $eco_label = get_option('shippingguard_zero_emission_label', 'Green Zero Emission Delivery');

        // Loop through all orders in range to get shipping and eco fee totals
        $all_orders_data = wc_get_orders(array(
            'limit'        => 500,
            'date_created' => $start_date . ' 00:00:00...' . $end_date . ' 23:59:59',
            'status'       => array_diff( array_keys( wc_get_order_statuses() ), array( 'wc-cancelled', 'wc-failed' ) ),
        ));

        foreach ($all_orders_data as $order) {
            // Check Shipping logic for logistics revenue
            foreach ($order->get_shipping_methods() as $shipping_item) {
                if ($shipping_item->get_method_id() === 'shippingguard_weight_shipping') {
                    $logistics_revenue += (float) $shipping_item->get_total();
                }
            }

            // Check Fees for eco deliveries
            foreach ($order->get_items('fee') as $fee_item) {
                if ($fee_item->get_name() === $eco_label) {
                    $eco_orders_count++;
                }
            }
        }

        // 4. Opt-in Rate
        $grand_total_orders = count( $all_orders_data );
        $opt_in_rate = $grand_total_orders > 0 ? round( ( $total_protected_orders / $grand_total_orders ) * 100, 2 ) : 0;

        // Roughly estimate net profit
        $payout_estimate = 0;
        foreach ( $claims as $claim ) {
            if ( $claim->status === 'Approved' || $claim->status === 'Refunded' ) {
                $order = wc_get_order( $claim->order_id );
                if ( $order ) $payout_estimate += (float) $order->get_total();
            }
        }
        $net_profit = $total_revenue - $payout_estimate;

        // Format chart data
        $chart_dates = array();
        $curr = strtotime( $start_date );
        $end  = strtotime( $end_date );
        while ( $curr <= $end ) {
            $chart_dates[] = gmdate( 'Y-m-d', $curr );
            $curr = strtotime( '+1 day', $curr );
        }

        $revenue_series = array();
        $claims_series = array();
        foreach ( $chart_dates as $d ) {
            $revenue_series[] = (float) ( $daily_revenue[ $d ] ?? 0 );
            $claims_series[]  = (int) ( $daily_claims[ $d ] ?? 0 );
        }

        return rest_ensure_response( array(
            'summary' => array(
                'protected_orders' => $total_protected_orders,
                'revenue'          => $total_revenue,
                'claims'           => $total_claims,
                'net_profit'       => $net_profit,
                'opt_in_rate'      => $opt_in_rate,
                'eco_orders'       => $eco_orders_count,
                'carbon_saved'     => round($eco_orders_count * 0.35, 1), // Estimate 0.35kg per delivery
                'logistics_fees'   => $logistics_revenue,
            ),
            'charts' => array(
                'dates'    => $chart_dates,
                'revenue'  => $revenue_series,
                'claims'   => $claims_series,
            ),
            'top_products' => array_values( $top_products ),
            'recent_claims' => array_slice( $claims, 0, 5 ),
        ) );
    }
}
