<?php
/**
 * api/analytics/behavior.php
 * Behaviour Analytics — how trader psychology affects performance.
 *
 * GET parameters:
 *   account_type        (required) 'prop_firm' or 'personal'
 *   strategy_version_id (optional)
 *   date_from           (optional) YYYY-MM-DD
 *   date_to             (optional) YYYY-MM-DD
 */

header('Content-Type: application/json');
require_once __DIR__ . '/../../config/config.php';
$dsn = "mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=utf8mb4";
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
require_once __DIR__ . '/../../src/Auth.php';
require_once __DIR__ . '/../../src/ScopedDb.php';
if (session_status() === PHP_SESSION_NONE) {
    if (defined('SESSION_NAME')) session_name(SESSION_NAME);
    session_start();
}
$auth = new Auth($pdo);
$userId = $auth->requireAuth();
$db = new ScopedDb($pdo, $userId);

// ── Input validation ──────────────────────────────────────────────────────────

$accountType = $_GET['account_type'] ?? null;
if (!in_array($accountType, ['prop_firm', 'personal'], true)) {
    http_response_code(400);
    echo json_encode(['error' => 'account_type must be "prop_firm" or "personal"']);
    exit;
}

$strategyVersionId = !empty($_GET['strategy_version_id']) ? (int)$_GET['strategy_version_id'] : null;

$dateFrom = null;
$dateTo   = null;
if (!empty($_GET['date_from'])) {
    $d = \DateTime::createFromFormat('Y-m-d', $_GET['date_from']);
    $dateFrom = $d ? $d->format('Y-m-d') : null;
}
if (!empty($_GET['date_to'])) {
    $d = \DateTime::createFromFormat('Y-m-d', $_GET['date_to']);
    $dateTo = $d ? $d->format('Y-m-d') : null;
}

// ── P&L expression: use challenge_pnl for prop firm, broker_pnl for personal ─
// Mirrors the same rule applied in dashboard.php stats queries.
$pnlExpr = $accountType === 'prop_firm'
    ? "CASE WHEN ta.account_type = 'prop_firm' THEN COALESCE(t.challenge_pnl, t.broker_pnl, t.projected_pnl, 0) ELSE COALESCE(t.broker_pnl, t.projected_pnl, 0) END"
    : "COALESCE(t.broker_pnl, t.projected_pnl, 0)";

// ── Base WHERE clause and params (shared across all queries) ──────────────────

$baseWhere  = "t.user_id = :uid AND t.status = 'closed' AND t.deleted_at IS NULL";
$baseParams = [':uid' => $userId];

if ($strategyVersionId) {
    $baseWhere .= " AND t.strategy_version_id = :svid";
    $baseParams[':svid'] = $strategyVersionId;
}
if ($dateFrom) {
    $baseWhere .= " AND DATE(t.captured_at) >= :date_from";
    $baseParams[':date_from'] = $dateFrom;
}
if ($dateTo) {
    $baseWhere .= " AND DATE(t.captured_at) <= :date_to";
    $baseParams[':date_to'] = $dateTo;
}

// Join trading_accounts so we can filter by account_type and drive the P&L expr.
$baseJoin = "LEFT JOIN trading_accounts ta ON ta.id = t.account_id AND ta.user_id = t.user_id";

// Constrain to the requested account type.
$baseWhere .= " AND (ta.account_type = :acct_type OR (ta.account_type IS NULL AND :acct_type2 = 'personal'))";
$baseParams[':acct_type']  = $accountType;
$baseParams[':acct_type2'] = $accountType;

// ── Helper: run a prepared statement, return all rows as assoc array ──────────

$query = function (string $sql, array $params) use ($pdo): array {
    try {
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (\Throwable $e) {
        error_log("behavior.php query error: " . $e->getMessage());
        return [];
    }
};

// ── Helper: build a per-level stat block (mood / energy / confidence) ─────────

$buildLevelStats = function (string $column) use ($query, $pdo, $baseJoin, $baseWhere, $baseParams, $pnlExpr): array {
    $sql = "
        SELECT
            t.{$column}                                                              AS level,
            COUNT(*)                                                                 AS total_trades,
            SUM(CASE WHEN ({$pnlExpr}) > 0 THEN 1 ELSE 0 END)                      AS wins,
            ROUND(AVG({$pnlExpr}), 2)                                               AS avg_pnl,
            ROUND(SUM({$pnlExpr}), 2)                                               AS total_pnl
        FROM trades t
        {$baseJoin}
        WHERE {$baseWhere}
          AND t.{$column} IS NOT NULL
          AND t.{$column} BETWEEN 1 AND 5
        GROUP BY t.{$column}
        ORDER BY t.{$column} ASC
    ";

    $rows = [];
    try {
        $stmt = $pdo->prepare($sql);
        $stmt->execute($baseParams);
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            $total = (int)$row['total_trades'];
            $rows[] = [
                'level'        => (int)$row['level'],
                'total_trades' => $total,
                'wins'         => (int)$row['wins'],
                'win_rate'     => $total > 0 ? round(((int)$row['wins'] / $total) * 100, 1) : null,
                'avg_pnl'      => (float)$row['avg_pnl'],
                'total_pnl'    => (float)$row['total_pnl'],
            ];
        }
    } catch (\Throwable $e) {
        error_log("behavior.php {$column} query error: " . $e->getMessage());
    }

    return $rows;
};

// ─────────────────────────────────────────────────────────────────────────────
// 1. Performance by Mood
// ─────────────────────────────────────────────────────────────────────────────

$moodPerformance = $buildLevelStats('mood_before');

// ─────────────────────────────────────────────────────────────────────────────
// 2. Performance by Energy
// ─────────────────────────────────────────────────────────────────────────────

$energyPerformance = $buildLevelStats('energy_before');

// ─────────────────────────────────────────────────────────────────────────────
// 3. Performance by Confidence
// ─────────────────────────────────────────────────────────────────────────────

$confidencePerformance = $buildLevelStats('confidence_before');

// ─────────────────────────────────────────────────────────────────────────────
// 4. Session Performance
// ─────────────────────────────────────────────────────────────────────────────

$sessionSql = "
    SELECT
        t.session,
        COUNT(*)                                                         AS total_trades,
        SUM(CASE WHEN ({$pnlExpr}) > 0 THEN 1 ELSE 0 END)              AS wins,
        ROUND(SUM({$pnlExpr}), 2)                                        AS total_pnl,
        ROUND(AVG({$pnlExpr}), 2)                                        AS avg_pnl,
        ROUND(AVG(t.risk_pct), 2)                                        AS avg_risk_pct
    FROM trades t
    {$baseJoin}
    WHERE {$baseWhere}
      AND t.session IS NOT NULL
    GROUP BY t.session
    ORDER BY total_trades DESC
";

$sessionRaw = $query($sessionSql, $baseParams);
$sessionPerformance = array_map(function ($row) {
    $total = (int)$row['total_trades'];
    return [
        'session'      => $row['session'],
        'total_trades' => $total,
        'wins'         => (int)$row['wins'],
        'win_rate'     => $total > 0 ? round(((int)$row['wins'] / $total) * 100, 1) : null,
        'total_pnl'    => (float)$row['total_pnl'],
        'avg_pnl'      => (float)$row['avg_pnl'],
        'avg_risk_pct' => $row['avg_risk_pct'] !== null ? (float)$row['avg_risk_pct'] : null,
    ];
}, $sessionRaw);

// ─────────────────────────────────────────────────────────────────────────────
// 5 & 6. Performance After Wins / After Losses
//
// Strategy: pull all closed trades ordered by captured_at, then walk the list
// in PHP to identify each trade that immediately follows a win or a loss. This
// avoids a correlated subquery and works correctly across any date range.
// ─────────────────────────────────────────────────────────────────────────────

$sequenceSql = "
    SELECT
        t.id,
        ({$pnlExpr})                  AS pnl,
        t.trade_classification
    FROM trades t
    {$baseJoin}
    WHERE {$baseWhere}
    ORDER BY t.captured_at ASC, t.id ASC
";

$sequenceRows = $query($sequenceSql, $baseParams);

$afterWin  = ['trades' => 0, 'wins' => 0, 'total_pnl' => 0.0];
$afterLoss = ['trades' => 0, 'wins' => 0, 'total_pnl' => 0.0, 'revenge_trades' => 0];

$prevResult = null; // 'win' | 'loss' | 'breakeven'
foreach ($sequenceRows as $row) {
    $pnl = (float)$row['pnl'];
    $isWin  = $pnl > 0;
    $isLoss = $pnl < 0;

    if ($prevResult === 'win') {
        $afterWin['trades']++;
        $afterWin['total_pnl'] += $pnl;
        if ($isWin) $afterWin['wins']++;
    } elseif ($prevResult === 'loss') {
        $afterLoss['trades']++;
        $afterLoss['total_pnl'] += $pnl;
        if ($isWin) $afterLoss['wins']++;
        if ($row['trade_classification'] === 'revenge_trade') $afterLoss['revenge_trades']++;
    }

    if ($isWin)       $prevResult = 'win';
    elseif ($isLoss)  $prevResult = 'loss';
    else              $prevResult = 'breakeven';
}

$afterWinTotal  = $afterWin['trades'];
$afterLossTotal = $afterLoss['trades'];

$performanceAfterWins = [
    'total_trades'        => $afterWinTotal,
    'wins'                => $afterWin['wins'],
    'win_rate'            => $afterWinTotal > 0 ? round(($afterWin['wins'] / $afterWinTotal) * 100, 1) : null,
    'avg_pnl'             => $afterWinTotal > 0 ? round($afterWin['total_pnl'] / $afterWinTotal, 2) : null,
    'total_pnl'           => round($afterWin['total_pnl'], 2),
];

$revengeRate = $afterLossTotal > 0
    ? round(($afterLoss['revenge_trades'] / $afterLossTotal) * 100, 1)
    : null;

$performanceAfterLosses = [
    'total_trades'          => $afterLossTotal,
    'wins'                  => $afterLoss['wins'],
    'win_rate'              => $afterLossTotal > 0 ? round(($afterLoss['wins'] / $afterLossTotal) * 100, 1) : null,
    'avg_pnl'               => $afterLossTotal > 0 ? round($afterLoss['total_pnl'] / $afterLossTotal, 2) : null,
    'total_pnl'             => round($afterLoss['total_pnl'], 2),
    'revenge_trade_count'   => $afterLoss['revenge_trades'],
    'revenge_trade_rate_pct'=> $revengeRate,
];

// ─────────────────────────────────────────────────────────────────────────────
// 7. Disciplined vs Undisciplined
// ─────────────────────────────────────────────────────────────────────────────

$disciplinedClasses   = ['disciplined_win', 'controlled_loss'];
$undisciplinedClasses = ['revenge_trade', 'tilt_warning', 'loss_high_risk'];

$disciplineSql = "
    SELECT
        CASE
            WHEN t.trade_classification IN ('disciplined_win', 'controlled_loss')       THEN 'disciplined'
            WHEN t.trade_classification IN ('revenge_trade', 'tilt_warning', 'loss_high_risk') THEN 'undisciplined'
            ELSE 'other'
        END                                                                       AS discipline_bucket,
        COUNT(*)                                                                  AS total_trades,
        SUM(CASE WHEN ({$pnlExpr}) > 0 THEN 1 ELSE 0 END)                       AS wins,
        ROUND(SUM({$pnlExpr}), 2)                                                AS total_pnl,
        ROUND(AVG({$pnlExpr}), 2)                                                AS avg_pnl
    FROM trades t
    {$baseJoin}
    WHERE {$baseWhere}
      AND t.trade_classification IN (
          'disciplined_win', 'controlled_loss',
          'revenge_trade', 'tilt_warning', 'loss_high_risk'
      )
    GROUP BY discipline_bucket
";

$disciplineRaw = $query($disciplineSql, $baseParams);

$disciplined   = null;
$undisciplined = null;

foreach ($disciplineRaw as $row) {
    $total = (int)$row['total_trades'];
    $entry = [
        'total_trades' => $total,
        'wins'         => (int)$row['wins'],
        'win_rate'     => $total > 0 ? round(((int)$row['wins'] / $total) * 100, 1) : null,
        'total_pnl'    => (float)$row['total_pnl'],
        'avg_pnl'      => (float)$row['avg_pnl'],
    ];
    if ($row['discipline_bucket'] === 'disciplined') {
        $disciplined = $entry;
    } elseif ($row['discipline_bucket'] === 'undisciplined') {
        $undisciplined = $entry;
    }
}

$pnlDelta = null;
if ($disciplined !== null && $undisciplined !== null) {
    $pnlDelta = round($disciplined['avg_pnl'] - $undisciplined['avg_pnl'], 2);
}

$disciplinedVsUndisciplined = [
    'disciplined'   => $disciplined   ?? ['total_trades' => 0, 'wins' => 0, 'win_rate' => null, 'total_pnl' => 0.0, 'avg_pnl' => 0.0],
    'undisciplined' => $undisciplined ?? ['total_trades' => 0, 'wins' => 0, 'win_rate' => null, 'total_pnl' => 0.0, 'avg_pnl' => 0.0],
    'avg_pnl_delta_disciplined_vs_undisciplined' => $pnlDelta,
];

// ─────────────────────────────────────────────────────────────────────────────
// Output
// ─────────────────────────────────────────────────────────────────────────────

echo json_encode([
    'meta' => [
        'account_type'        => $accountType,
        'strategy_version_id' => $strategyVersionId,
        'date_from'           => $dateFrom,
        'date_to'             => $dateTo,
    ],
    'mood_performance'               => $moodPerformance,
    'energy_performance'             => $energyPerformance,
    'confidence_performance'         => $confidencePerformance,
    'session_performance'            => $sessionPerformance,
    'performance_after_wins'         => $performanceAfterWins,
    'performance_after_losses'       => $performanceAfterLosses,
    'disciplined_vs_undisciplined'   => $disciplinedVsUndisciplined,
], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);