<?php
require_once __DIR__ . '/../../engine/engine.php';
require_once __DIR__ . '/../../engine/api-handling/fmp_client.php';

header('Content-Type: application/json');

// Multi-Depot: pid aus GET (fallback 1)
$pid = isset($_GET['portfolio_id']) ? (int)$_GET['portfolio_id']
     : (isset($_GET['pid']) ? (int)$_GET['pid'] : 1);

// 1) Startkapital (portfolio-spezifisch)
try {
    $stmtSC = $pdo->prepare("SELECT meta_value FROM depot_meta WHERE meta_key='start_capital' AND portfolio_id = :pid");
    $stmtSC->execute([':pid' => $pid]);
    $startCash = (float)($stmtSC->fetchColumn() ?: 0);
} catch (Throwable $e) { $startCash = 0.0; }

// Cashflows (Ein-/Auszahlungen) pro Depot
$stmtFlows = $pdo->prepare("
  SELECT flow_date, type, amount
  FROM depot_cash
  WHERE type IN ('deposit','withdraw') AND is_snapshot = 0 AND portfolio_id = :pid
");
$stmtFlows->execute([':pid' => $pid]);
$flows = $stmtFlows->fetchAll(PDO::FETCH_ASSOC);

$flowByDate = [];
foreach ($flows as $f) {
  $amt = (float)$f['amount'];
  $sign = ($f['type'] === 'deposit') ? +1 : -1; // deposit +, withdraw -
  $flowByDate[$f['flow_date']] = ($flowByDate[$f['flow_date']] ?? 0) + $sign * $amt;
}

// 2) Einträge (portfolio-spezifisch)
$stmt = $pdo->prepare("
  SELECT id, symbol, shares, buy_price, buy_date, fees,
         status, sell_price, sell_date, sell_fees
  FROM depot_entries
  WHERE portfolio_id = :pid
  ORDER BY buy_date ASC, id ASC
");
$stmt->execute([':pid' => $pid]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!$rows) { echo json_encode(['labels'=>[], 'series'=>['value'=>[], 'cash'=>[], 'return'=>[], 'drawdown'=>[]]]); exit; }

// 3) Zeitraum
$minBuy = '9999-12-31';
$maxTxn = '0000-01-01';
foreach ($rows as $r) {
    $bd = substr((string)$r['buy_date'], 0, 10);
    if ($bd && $bd < $minBuy) $minBuy = $bd;
    $sd = !empty($r['sell_date']) ? substr((string)$r['sell_date'], 0, 10) : null;
    if ($sd && $sd > $maxTxn) $maxTxn = $sd;
}
$today = (new DateTime('today'))->format('Y-m-d');
$upperBound = max($today, $maxTxn);

// 4) Preise laden (Multi-Fetch via fmp_client)
$symbols = array_values(array_unique(array_map(fn($r)=>$r['symbol'], $rows)));

$hist = [];
if ($symbols) {
    // 4.1 Requests vorbereiten (ein Request je Symbol, ab $minBuy, serietype=line)
    $req = [];
    foreach ($symbols as $sym) {
        $req[$sym] = [
            'key'   => 'historical_price_full',
            'vars'  => ['symbol' => $sym],
            'query' => [
                'from'      => $minBuy,
                'serietype' => 'line',
            ],
        ];
    }

    // 4.2 Parallel abfeuern (Concurrency moderat auf 8–12)
    $resp = fmp_multi($req, min(12, max(4, count($req))));

    // 4.3 Robust entpacken & in dein bestehendes Format bringen
    foreach ($symbols as $sym) {
        $node = $resp[$sym] ?? [];

        // Wrapper-Varianten / JSON-String / stdClass tolerant entpacken
        if (is_string($node)) {
            $tmp = json_decode($node, true);
            if (json_last_error() === JSON_ERROR_NONE) $node = $tmp;
        }
        if (is_object($node)) $node = json_decode(json_encode($node), true);
        if (is_array($node) && isset($node['body'])) $node = $node['body'];
        if (is_array($node) && isset($node['data'])) $node = $node['data'];

        // FMP liefert typischerweise: { symbol, historical: [...] }
        $rowsHist = [];
        if (isset($node['historical']) && is_array($node['historical'])) {
            $rowsHist = $node['historical'];
        } elseif (is_array($node) && array_key_exists(0, $node)) {
            // Fallback: direkte Liste
            $rowsHist = $node;
        }

        // wie bisher: $series[date] = price (adjClose bevorzugt)
        $series = [];
        foreach ($rowsHist as $row) {
            $date = $row['date'] ?? null;
            if (!$date || $date > $upperBound) continue;
            $price = $row['adjClose'] ?? ($row['close'] ?? null);
            if ($price === null) continue;
            $series[$date] = (float)$price;
        }
        ksort($series);
        $hist[$sym] = $series;
    }
}

// 5) Zeitachse: Handelstage + alle Kauf-/Verkaufstage + Baseline-Tag vor erstem Kauf
$all = [];
foreach ($hist as $series) foreach ($series as $d => $_) $all[$d] = true;
foreach ($rows as $r) {
    $bd = substr((string)$r['buy_date'], 0, 10);
    if ($bd && $bd >= $minBuy && $bd <= $upperBound) $all[$bd] = true;
    $sd = !empty($r['sell_date']) ? substr((string)$r['sell_date'], 0, 10) : null;
    if ($sd && $sd >= $minBuy && $sd <= $upperBound) $all[$sd] = true;
}
$baseline = (new DateTime($minBuy))->modify('-1 day')->format('Y-m-d');
$all[$baseline] = true;

$dates = array_keys($all);
sort($dates);

// 6) Transaktionen (inkl. Gebühren)
$txByDate = []; // [$date][] = ['sym','deltaShares','cashFlow']
foreach ($rows as $r) {
    $sym   = $r['symbol'];
    $qty   = (float)$r['shares'];
    $buyP  = (float)$r['buy_price'];
    $buyD  = substr((string)$r['buy_date'], 0, 10);
    $buyF  = (float)($r['fees'] ?? 0);

    if ($qty > 0 && $buyD) {
        $txByDate[$buyD][] = ['sym'=>$sym, 'deltaShares'=> +$qty, 'cashFlow'=> -($qty*$buyP) - $buyF, 'type'=>'buy', 'px'=>$buyP];
    }

    if (($r['status'] ?? 'active') === 'sold' && !empty($r['sell_date'])) {
        $sellD  = substr((string)$r['sell_date'], 0, 10);
        $sellP  = (float)($r['sell_price'] ?? 0);
        $sellF  = (float)($r['sell_fees'] ?? 0);
        $sellQty = (float)$r['shares'];
        if ($sellD) {
            $txByDate[$sellD][] = ['sym'=>$sym, 'deltaShares'=> -$sellQty, 'cashFlow'=> +($sellQty*$sellP) - $sellF, 'type'=>'sell', 'px'=>$sellP];
        }
    }
}

// 7) Preisanker: an Kauf-/Verkaufstagen Kurs = Transaktionspreis
foreach ($txByDate as $d => $txs) {
    foreach ($txs as $t) {
        $sym = $t['sym'];
        $px  = $t['px'] ?? null;
        if ($px !== null) {
            if (!isset($hist[$sym])) $hist[$sym] = [];
            $hist[$sym][$d] = (float)$px;
        }
    }
}

// 8) Forward-Fill Preise auf volle Zeitachse (inkl. Baseline/Transaktionstage)
foreach ($hist as $sym => $series) {
    $last = null; $filled = [];
    foreach ($dates as $d) {
        if (isset($series[$d])) $last = $series[$d];
        if ($last !== null) $filled[$d] = $last;
    }
    $hist[$sym] = $filled;
}

// 9) Serien berechnen (TWRR, Drawdown)
$cash = (float)$startCash;
$shares = array_fill_keys($symbols, 0.0);
$twrr = 1.0; 
$prevTotal = null; 
$runMax = null;

$seriesValue = []; $seriesCash = []; $seriesRet = []; $seriesDD = [];

foreach ($dates as $d) {
    // 1) externe Cashflows (Einzahlung/Auszahlung)
    $externalCF = $flowByDate[$d] ?? 0.0;
    if ($externalCF != 0.0) {
        $cash += $externalCF;
    }

    // 2) Trades am Tag
    if (!empty($txByDate[$d])) {
        foreach ($txByDate[$d] as $t) {
            $shares[$t['sym']] += (float)$t['deltaShares'];
            $cash               += (float)$t['cashFlow'];
        }
    }

    // 3) Equity
    $equity = 0.0;
    foreach ($symbols as $sym) {
        $p = $hist[$sym][$d] ?? null;
        if ($p !== null) $equity += $shares[$sym] * $p;
    }
    $total = $equity + $cash;

    // 4) TWRR – Cashflows neutralisieren
    if ($prevTotal !== null && $prevTotal > 0) {
        $rt = ($total - $prevTotal - $externalCF) / $prevTotal;
        $twrr *= (1.0 + $rt);
    }
    $prevTotal = $total;

    // 5) Drawdown
    if ($runMax === null || $total > $runMax) $runMax = $total;
    $ddPct = ($total / $runMax - 1.0) * 100.0;

    // 6) Serien füllen
    $seriesValue[] = round($total, 2);
    $seriesCash[]  = round($cash, 2);
    $seriesRet[]   = round(($twrr - 1.0) * 100.0, 2);
    $seriesDD[]    = round($ddPct, 2);
}

echo json_encode([
  'labels' => $dates,
  'series' => [
    'value'    => $seriesValue,
    'cash'     => $seriesCash,
    'return'   => $seriesRet,
    'drawdown' => $seriesDD,
  ],
  'debug' => [
    'startCash' => $startCash,
    'baseline'  => $baseline,
  ],
], JSON_UNESCAPED_UNICODE);