<?php

class RiskScoringEngine
{
    public static function apply(array $tradePlan, array $newsRisk, array $geoRisk): array
    {
        $scheduledRisk = strtoupper((string)($newsRisk['scheduled_risk'] ?? ($newsRisk['risk'] ?? 'LOW')));
        $hasScheduledEvent = !empty($newsRisk['has_scheduled_event']) || !empty($newsRisk['has_news']);
        $minutesUntil = $newsRisk['minutes_until'] ?? null;

        $geoRiskLevel = strtoupper((string)($geoRisk['risk'] ?? 'LOW'));

        $originalScore = (float)($tradePlan['score'] ?? 0);

        /*
        |--------------------------------------------------------------------------
        | INSTITUTIONAL RISK LOGIC
        |--------------------------------------------------------------------------
        | Technical structure remains PRIMARY.
        | Macro + geopolitical layers only modify execution aggressiveness.
        | They should NEVER automatically kill valid setups.
        |--------------------------------------------------------------------------
        */

        $penalty = 0;

        /*
        |--------------------------------------------------------------------------
        | Scheduled News Logic
        |--------------------------------------------------------------------------
        | Upcoming news should NOT invalidate setups.
        | Only reduce execution aggressiveness slightly.
        |--------------------------------------------------------------------------
        */

        if ($hasScheduledEvent) {

            if ($scheduledRisk === 'HIGH') {
                $penalty -= 1.0;
            } elseif ($scheduledRisk === 'MEDIUM') {
                $penalty -= 0.5;
            }

            $tradePlan['news_caution'] = true;

            if ($minutesUntil !== null) {

                if ((int)$minutesUntil >= 0) {

                    $tradePlan['execution_mode'] = 'NEWS_CAUTION';

                    $tradePlan['message'] =
                        'A high-impact news event is scheduled ' .
                        self::countdownLabel((int)$minutesUntil) .
                        '. Technical setup remains valid, but avoid execution close to the release window.';

                } else {

                    $tradePlan['execution_mode'] = 'POST_NEWS_VOLATILITY';

                    $tradePlan['message'] =
                        'A high-impact news event was released recently. Allow volatility to stabilize before execution.';
                }

            } else {

                $tradePlan['execution_mode'] = 'NEWS_CAUTION';

                $tradePlan['message'] =
                    'A high-impact macro event is active. Reduce exposure and wait for cleaner confirmation.';
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Geopolitical Logic
        |--------------------------------------------------------------------------
        | Geopolitical risk should REDUCE CONFIDENCE,
        | not automatically invalidate setups.
        |--------------------------------------------------------------------------
        */

        if ($geoRiskLevel === 'HIGH') {

            $penalty -= 1.0;

            $tradePlan['geo_warning'] = true;

            $tradePlan['risk_guidance'] =
                'Geopolitical volatility is elevated. Reduce exposure and require stronger confirmation before execution.';

            /*
            |--------------------------------------------------------------------------
            | Only force WAIT if setup is already weak technically.
            |--------------------------------------------------------------------------
            */

            if ($originalScore < 4) {

                $tradePlan['execution_mode'] = 'REDUCED_RISK';

                if (empty($tradePlan['message'])) {
                    $tradePlan['message'] =
                        'Geopolitical volatility is elevated and technical confluence is weak. Wait for stronger confirmation.';
                }

            } else {

                /*
                |--------------------------------------------------------------------------
                | Strong technical setups remain VALID.
                |--------------------------------------------------------------------------
                */

                $tradePlan['execution_mode'] = 'REDUCED_RISK';

                if (empty($tradePlan['message'])) {
                    $tradePlan['message'] =
                        'Technical setup remains valid, but geopolitical volatility is elevated. Use reduced risk.';
                }
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Apply Controlled Penalty
        |--------------------------------------------------------------------------
        */

        $finalScore = $originalScore + $penalty;

        /*
        |--------------------------------------------------------------------------
        | Prevent macro/news layers from killing good setups.
        |--------------------------------------------------------------------------
        */

        if ($originalScore >= 6) {
            $finalScore = max($finalScore, 5.5);
        }

        if ($originalScore >= 4 && $finalScore < 3) {
            $finalScore = 3.5;
        }

        $tradePlan['score_before_risk'] = round($originalScore, 2);
        $tradePlan['score'] = round(max(0, $finalScore), 2);

        $tradePlan['macro_risk_penalty'] = $penalty;

        /*
        |--------------------------------------------------------------------------
        | Preserve valid technical setup states
        |--------------------------------------------------------------------------
        */

        $currentStatus = strtoupper((string)($tradePlan['status'] ?? ''));

        if (
            !in_array(
                $currentStatus,
                ['NO_DATA', 'NO DATA', 'INVALID'],
                true
            )
        ) {

            /*
            |--------------------------------------------------------------------------
            | Only set WAIT if technical quality is genuinely weak.
            |--------------------------------------------------------------------------
            */

            if ($tradePlan['score'] < 3) {

                $tradePlan['status'] = 'WAIT';

            } else {

                /*
                |--------------------------------------------------------------------------
                | Preserve directional setup
                |--------------------------------------------------------------------------
                */

                if (empty($tradePlan['status']) || $tradePlan['status'] === 'WAIT') {

                    $tradePlan['status'] =
                        strtoupper((string)($tradePlan['bias'] ?? 'WAIT'));
                }
            }
        }

        /*
        |--------------------------------------------------------------------------
        | Default execution mode
        |--------------------------------------------------------------------------
        */

        if (empty($tradePlan['execution_mode'])) {
            $tradePlan['execution_mode'] = 'NORMAL';
        }

        return $tradePlan;
    }

    private static function countdownLabel(int $minutes): string
    {
        if ($minutes < 0) {
            return abs($minutes) . ' minutes ago';
        }

        if ($minutes < 60) {
            return 'in ' . $minutes . ' minutes';
        }

        $hours = intdiv($minutes, 60);
        $mins = $minutes % 60;

        return 'in ' . $hours . 'h' . ($mins ? ' ' . $mins . 'm' : '');
    }
}
