<?php
/**
 * Plugin Name: STB Live Sentiment
 * Description: Pulls technical analysis sentiment (Recommend.All) from TradingView
 *              scanner for 8 symbols, maps to bullish% (15-90 range), exposes via
 *              /wp-json/stb/v1/sentiment. Cached 15 min server-side.
 * Version: 1.0
 */

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

// ─── Symbol catalogue ──────────────────────────────────────────────────────
// UI display label => TradingView scanner ticker
define( 'STB_SENT_SYMBOLS', [
    'EUR/USD' => 'FX:EURUSD',
    'GBP/USD' => 'FX:GBPUSD',
    'USD/JPY' => 'FX:USDJPY',
    'XAU/USD' => 'OANDA:XAUUSD',
    'NAS100'  => 'NASDAQ:NDX',
    'SPX500'  => 'SP:SPX',
    'BTC/USD' => 'COINBASE:BTCUSD',
    'US Oil'  => 'NYMEX:CL1!',
] );

// ─── Fetch from TradingView ────────────────────────────────────────────────

function stb_sentiment_fetch(): array {
    $tickers = array_values( STB_SENT_SYMBOLS );
    $resp = wp_remote_post( 'https://scanner.tradingview.com/global/scan', [
        'body'    => wp_json_encode( [
            'symbols' => [ 'tickers' => $tickers ],
            'columns' => [ 'Recommend.All', 'Recommend.MA', 'Recommend.Other', 'RSI' ],
        ] ),
        'headers' => [
            'Content-Type' => 'application/json',
            'User-Agent'   => 'Mozilla/5.0',
            'Origin'       => 'https://www.tradingview.com',
            'Referer'      => 'https://www.tradingview.com/',
        ],
        'timeout' => 10,
    ] );
    if ( is_wp_error( $resp ) ) {
        update_option( 'stb_sent_last_error', $resp->get_error_message() );
        return [];
    }
    $json = json_decode( wp_remote_retrieve_body( $resp ), true );
    if ( empty( $json['data'] ) ) {
        update_option( 'stb_sent_last_error', 'empty data' );
        return [];
    }

    // Map ticker → row
    $by_ticker = [];
    foreach ( $json['data'] as $row ) {
        $by_ticker[ $row['s'] ] = $row['d'];
    }

    $out = [];
    foreach ( STB_SENT_SYMBOLS as $sym => $ticker ) {
        if ( ! isset( $by_ticker[ $ticker ] ) ) continue;
        $d   = $by_ticker[ $ticker ];
        $rec = is_numeric( $d[0] ?? null ) ? (float) $d[0] : 0.0;  // -1..+1
        $ma  = is_numeric( $d[1] ?? null ) ? (float) $d[1] : 0.0;
        $osc = is_numeric( $d[2] ?? null ) ? (float) $d[2] : 0.0;
        $rsi = is_numeric( $d[3] ?? null ) ? (float) $d[3] : 50.0;

        // Map -1..+1 to 15..90 (matching existing UI range)
        // -1 → 15  |  0 → 52.5  |  +1 → 90
        $bull = (int) round( 15 + ( ( $rec + 1 ) * 37.5 ) );
        $bull = max( 15, min( 90, $bull ) );

        if ( $rec >= 0.5 ) {
            $label = 'STRONG BUY';
        } elseif ( $rec >= 0.1 ) {
            $label = 'BUY';
        } elseif ( $rec > -0.1 ) {
            $label = 'NEUTRAL';
        } elseif ( $rec > -0.5 ) {
            $label = 'SELL';
        } else {
            $label = 'STRONG SELL';
        }

        $out[] = [
            'sym'   => $sym,
            'bull'  => $bull,
            'bear'  => 100 - $bull,
            'rec'   => round( $rec, 3 ),
            'ma'    => round( $ma, 3 ),
            'osc'   => round( $osc, 3 ),
            'rsi'   => round( $rsi, 1 ),
            'label' => $label,
        ];
    }
    update_option( 'stb_sent_last_ok', time(), false );
    return $out;
}

// ─── Cache refresh ─────────────────────────────────────────────────────────

function stb_sentiment_refresh(): void {
    $data = stb_sentiment_fetch();
    if ( ! empty( $data ) ) {
        set_transient( 'stb_sentiment_v1', $data, 1800 ); // 30 min TTL
        update_option( 'stb_sent_last_feed', $data, false );
    }
}

// ─── Cron: every 15 minutes ────────────────────────────────────────────────

add_filter( 'cron_schedules', function ( $s ) {
    if ( ! isset( $s['stb_15min'] ) ) {
        $s['stb_15min'] = [ 'interval' => 900, 'display' => 'Every 15 minutes' ];
    }
    return $s;
} );

add_action( 'init', function () {
    if ( ! wp_next_scheduled( 'stb_sent_cron' ) ) {
        wp_schedule_event( time() + 30, 'stb_15min', 'stb_sent_cron' );
    }
} );
add_action( 'stb_sent_cron', 'stb_sentiment_refresh' );

// ─── REST endpoint ─────────────────────────────────────────────────────────

add_action( 'rest_api_init', function () {
    register_rest_route( 'stb/v1', '/sentiment', [
        'methods'             => 'GET',
        'permission_callback' => '__return_true',
        'callback'            => function () {
            $data  = get_transient( 'stb_sentiment_v1' );
            $stale = false;
            if ( empty( $data ) ) {
                stb_sentiment_refresh();
                $data = get_transient( 'stb_sentiment_v1' );
            }
            if ( empty( $data ) ) {
                $data  = get_option( 'stb_sent_last_feed', [] );
                $stale = true;
            }
            return new WP_REST_Response( [
                'ok'         => ! empty( $data ),
                'stale'      => $stale,
                'count'      => count( (array) $data ),
                'updated_at' => (int) get_option( 'stb_sent_last_ok', 0 ),
                'sentiment'  => $data,
                'source'     => 'TradingView technical analysis',
            ], 200, [
                'Cache-Control'               => 'public, max-age=120',
                'Access-Control-Allow-Origin' => '*',
            ] );
        },
    ] );
} );

// ─── Warm-up on first request ──────────────────────────────────────────────

add_action( 'init', function () {
    if ( ! get_transient( 'stb_sentiment_v1' ) && ! get_option( 'stb_sent_warm_attempted' ) ) {
        update_option( 'stb_sent_warm_attempted', time(), false );
        wp_schedule_single_event( time() + 5, 'stb_sent_cron' );
    }
} );
