<?php

class VolatilityService
{
    /*
    |--------------------------------------------------------------------------
    | ATR Calculation
    |--------------------------------------------------------------------------
    */

    public static function calculateATR(array $candles, int $period = 14): float
    {
        if (count($candles) < ($period + 1)) {
            return 0;
        }

        $trs = [];

        for ($i = 1; $i < count($candles); $i++) {

            $current = $candles[$i];
            $previous = $candles[$i - 1];

            $high = (float)$current['high_price'];
            $low = (float)$current['low_price'];
            $prevClose = (float)$previous['close_price'];

            $tr = max(
                $high - $low,
                abs($high - $prevClose),
                abs($low - $prevClose)
            );

            $trs[] = $tr;
        }

        $recentTRs = array_slice($trs, -$period);

        if (empty($recentTRs)) {
            return 0;
        }

        return array_sum($recentTRs) / count($recentTRs);
    }

    /*
    |--------------------------------------------------------------------------
    | Symbol Minimum Stop Loss
    |--------------------------------------------------------------------------
    |
    | Prevent unrealistic institutional stop losses
    |
    */

    public static function getMinimumStopDistance(string $symbol): float
    {
        return match ($symbol) {

            // Gold
            'XAUUSD' => 3.0,

            // Yen pairs
            'USDJPY',
            'GBPJPY',
            'EURJPY' => 0.20,

            // GBP pairs
            'GBPUSD',
            'GBPAUD',
            'GBPCHF',
            'GBPCAD' => 0.0025,

            // Default FX
            default => 0.0020
        };
    }

    /*
    |--------------------------------------------------------------------------
    | Dynamic ATR Stop Distance
    |--------------------------------------------------------------------------
    */

    public static function getATRStopDistance(
        string $symbol,
        array $candles,
        float $multiplier = 1.5
    ): float {

        $atr = self::calculateATR($candles);

        $minimum = self::getMinimumStopDistance($symbol);

        if ($atr <= 0) {
            return $minimum;
        }

        $atrDistance = $atr * $multiplier;

        return max($minimum, $atrDistance);
    }

    /*
    |--------------------------------------------------------------------------
    | Institutional Stop Loss
    |--------------------------------------------------------------------------
    */

    public static function buildStopLoss(
        string $direction,
        float $entryLow,
        float $entryHigh,
        array $candles,
        string $symbol
    ): float {

        $distance = self::getATRStopDistance(
            $symbol,
            $candles
        );

        if ($direction === 'BUY') {

            return round(
                $entryLow - $distance,
                self::getPrecision($symbol)
            );
        }

        return round(
            $entryHigh + $distance,
            self::getPrecision($symbol)
        );
    }

    /*
    |--------------------------------------------------------------------------
    | TP Levels
    |--------------------------------------------------------------------------
    */

    public static function buildTakeProfits(
        string $direction,
        float $entryPrice,
        float $stopLoss,
        string $symbol
    ): array {

        $risk = abs($entryPrice - $stopLoss);

        if ($risk <= 0) {
            return [
                'tp1' => null,
                'tp2' => null,
                'tp3' => null,
                'rr' => 0
            ];
        }

        if ($direction === 'BUY') {

            $tp1 = $entryPrice + ($risk * 1.5);

            $tp2 = $entryPrice + ($risk * 2.5);

            $tp3 = $entryPrice + ($risk * 4.0);

        } else {

            $tp1 = $entryPrice - ($risk * 1.5);

            $tp2 = $entryPrice - ($risk * 2.5);

            $tp3 = $entryPrice - ($risk * 4.0);
        }

        return [

            'tp1' => round($tp1, self::getPrecision($symbol)),

            'tp2' => round($tp2, self::getPrecision($symbol)),

            'tp3' => round($tp3, self::getPrecision($symbol)),

            'rr' => 2.5
        ];
    }

    /*
    |--------------------------------------------------------------------------
    | Volatility Classification
    |--------------------------------------------------------------------------
    */

    public static function classifyVolatility(
        string $symbol,
        float $atr
    ): string {

        if ($symbol === 'XAUUSD') {

            if ($atr >= 8) return 'EXTREME';
            if ($atr >= 4) return 'HIGH';
            if ($atr >= 2) return 'NORMAL';

            return 'LOW';
        }

        if ($atr >= 0.0080) return 'EXTREME';

        if ($atr >= 0.0040) return 'HIGH';

        if ($atr >= 0.0015) return 'NORMAL';

        return 'LOW';
    }

    /*
    |--------------------------------------------------------------------------
    | Entry Quality Filter
    |--------------------------------------------------------------------------
    */

    public static function isSpreadTooWide(
        float $entryLow,
        float $entryHigh,
        string $symbol
    ): bool {

        $spread = abs($entryHigh - $entryLow);

        $maxAllowed = match ($symbol) {

            'XAUUSD' => 2.5,

            default => 0.0035
        };

        return $spread > $maxAllowed;
    }

    /*
    |--------------------------------------------------------------------------
    | Precision
    |--------------------------------------------------------------------------
    */

    public static function getPrecision(string $symbol): int
    {
        return match ($symbol) {

            'XAUUSD' => 2,

            'USDJPY',
            'EURJPY',
            'GBPJPY' => 3,

            default => 5
        };
    }
} 