<?php

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../services/MarketDataProviderService.php';

/*
|--------------------------------------------------------------------------
| Rotating Candle Backfill Worker
|--------------------------------------------------------------------------
| Features:
| - Multi-provider candle ingestion
| - Binance Vision crypto routing
| - Timeframe normalization
| - Safe candle upsert
| - CLI symbol/timeframe override
| - Detailed terminal logging
|--------------------------------------------------------------------------
*/

function out($msg)
{
    echo '[' . date('Y-m-d H:i:s') . '] ' . $msg . PHP_EOL;
}

/*
|--------------------------------------------------------------------------
| Active Symbols
|--------------------------------------------------------------------------
*/
function active_symbols()
{
    global $argv;

    if (!empty($argv[1])) {
        return [[
            'symbol' => strtoupper(trim($argv[1]))
        ]];
    }

    return db()->query("
        SELECT *
        FROM symbols
        WHERE is_active = 1
        ORDER BY symbol ASC
    ")->fetchAll(PDO::FETCH_ASSOC) ?: [];
}

/*
|--------------------------------------------------------------------------
| Active Timeframes
|--------------------------------------------------------------------------
| IMPORTANT:
| Binance expects lowercase intervals:
| 1h, 4h, 1d, etc.
|--------------------------------------------------------------------------
*/
function active_timeframes()
{
    global $argv;

    if (!empty($argv[2])) {

        $manual = trim($argv[2]);

        return [[
            'code' => strtoupper($manual),
            'api_interval' => strtolower($manual)
        ]];
    }

    return db()->query("
        SELECT
            *,
            LOWER(api_interval) AS api_interval
        FROM timeframes
        WHERE is_active = 1
        ORDER BY id ASC
    ")->fetchAll(PDO::FETCH_ASSOC) ?: [];
}

/*
|--------------------------------------------------------------------------
| Insert Candle
|--------------------------------------------------------------------------
*/
function insert_candle($symbol, $timeframe, $candle)
{
    $openTime =
        $candle['datetime']
        ?? $candle['time']
        ?? $candle['timestamp']
        ?? $candle['open_time']
        ?? null;

    if (is_numeric($openTime)) {
        $openTime = date('Y-m-d H:i:s', (int)$openTime);
    } elseif ($openTime) {
        $openTime = date('Y-m-d H:i:s', strtotime($openTime));
    }

    if (!$openTime) {
        return false;
    }

    $stmt = db()->prepare("
        INSERT INTO candles
        (
            symbol,
            timeframe,
            open_time,
            open_price,
            high_price,
            low_price,
            close_price,
            volume,
            created_at
        )
        VALUES
        (
            ?, ?, ?, ?, ?, ?, ?, ?, NOW()
        )
        ON DUPLICATE KEY UPDATE
            open_price = VALUES(open_price),
            high_price = VALUES(high_price),
            low_price = VALUES(low_price),
            close_price = VALUES(close_price),
            volume = VALUES(volume)
    ");

    return $stmt->execute([
        strtoupper($symbol),
        strtoupper($timeframe),
        $openTime,
        (float)($candle['open'] ?? $candle['o'] ?? 0),
        (float)($candle['high'] ?? $candle['h'] ?? 0),
        (float)($candle['low'] ?? $candle['l'] ?? 0),
        (float)($candle['close'] ?? $candle['c'] ?? 0),
        (float)($candle['volume'] ?? $candle['v'] ?? 0),
    ]);
}

/*
|--------------------------------------------------------------------------
| Output Size
|--------------------------------------------------------------------------
*/
$outputSize = !empty($argv[3])
    ? (int)$argv[3]
    : 20;

/*
|--------------------------------------------------------------------------
| Main Worker Loop
|--------------------------------------------------------------------------
*/
foreach ([['symbol' => 'BTCUSD']] as $symbolRow) {

    $symbol = strtoupper(trim($symbolRow['symbol'] ?? ''));

    if ($symbol === '') {
        continue;
    }

    foreach (active_timeframes() as $tf) {

        $timeframe =
            strtoupper(
                trim(
                    $tf['code']
                    ?? $tf['timeframe']
                    ?? ''
                )
            );

        /*
        |--------------------------------------------------------------------------
        | CRITICAL FIX
        |--------------------------------------------------------------------------
        | Binance requires lowercase intervals:
        | 1h, 4h, 1d...
        |--------------------------------------------------------------------------
        */
        $interval =
            strtolower(
                trim(
                    $tf['api_interval']
                    ?? $timeframe
                )
            );

        out("Fetching {$symbol} {$timeframe} ({$interval}) using provider rotation...");

        try {

            $result = MarketDataProviderService::fetchCandles(
                $symbol,
                $timeframe,
                $interval,
                $outputSize
            );

            if (empty($result['success'])) {

                out(
                    'FAILED: ' .
                    ($result['error'] ?? 'Unknown error')
                );

                continue;
            }

            $candles = $result['candles'] ?? [];

            if (!$candles) {
                out('FAILED: No candles returned.');
                continue;
            }

            $inserted = 0;

            foreach ($candles as $candle) {

                if (insert_candle($symbol, $timeframe, $candle)) {
                    $inserted++;
                }
            }

            $provider =
                $result['provider']['provider']
                ?? 'unknown';

            out(
                "Done: {$inserted} candles inserted/updated via {$provider}."
            );

        } catch (Throwable $e) {

            out(
                'EXCEPTION: ' .
                $e->getMessage()
            );
        }

        sleep(1);
    }
}

