<?php
$symbol     = $GLOBALS['tab_symbol'] ?? '';
$asof       = $GLOBALS['tab_asof'] ?? null;
$target_pe  = $GLOBALS['tab_target_pe'] ?? null;

require_once __DIR__ . '/../../engine/api-handling/fmp_client.php';
$data = [];
$eodRaw = $data['raw']['historical']['historical'] ?? [];

$eod_dates = [];
$eod_closes = [];

// --- FMP data via fmp_client.php (no logic changes, nur Daten-Wiring) ---
try {
	if (!isset($symbol) || !$symbol) {
		throw new \RuntimeException('Symbol fehlt.');
	}

	if (!function_exists('fmp_multi')) {
		throw new \RuntimeException('fmp_multi() nicht verfügbar – bitte fmp_client.php einbinden.');
	}

	// Registry-Key 'historical_price_full' mit Variablen + Query
	$requests = [
		'historical' => [
			'key'   => 'historical_price_full',
			'vars'  => ['symbol' => $symbol],
			'query' => ['timeseries' => 800],
		],
	];
	$responses = fmp_multi($requests, 12);

	$rows = [];
	$h = $responses['historical'] ?? null;
	if (is_array($h)) {
		if (isset($h['historical']) && is_array($h['historical'])) {
			$rows = $h['historical'];
		} elseif (isset($h['historicalStockList'][0]['historical'])) {
			$rows = $h['historicalStockList'][0]['historical'];
		} else {
			$rows = $h;
		}
	}

	if (is_array($rows)) {
		// FMP liefert i. d. R. neueste zuerst. Stelle sicher, dass $eodRaw neueste->älteste bleibt.
		// Falls die Reihenfolge doch gemischt ist, sortieren und anschließend reverse:
		usort($rows, function($a, $b){
			return strcmp($a['date'] ?? '', $b['date'] ?? ''); // älteste->neueste
		});
		$rows = array_reverse($rows); // neueste->älteste

		// Nur $eodRaw befüllen; nachfolgende Logik erzeugt daraus $eod_dates/$eod_closes/$eod_highs/$eod_lows
		$eodRaw = $rows;
	}
} catch (\Throwable $ex) {
	error_log('[tab_technical] FMP Fetch Error: ' . $ex->getMessage());
}
// --- End data wiring ---


$eod_highs = [];
$eod_lows  = [];

if (!empty($symbol) && !empty($eodRaw)) {
	foreach ($eodRaw as $item) {
		if (!isset($item['date'], $item['close'])) continue;

		$eod_dates[]  = $item['date'];
		$eod_closes[] = round($item['close'], 2);

		// High/Low einzeln prüfen und NULL eintragen, wenn nicht vorhanden
		$eod_highs[] = isset($item['high']) ? round($item['high'], 2) : null;
		$eod_lows[]  = isset($item['low'])  ? round($item['low'], 2)  : null;
	}
}

// Preisangabe
$currentPrice  = $eod_closes[0] ?? null;
$previousPrice = $eod_closes[1] ?? null;
$currentDate   = $eod_dates[0] ?? null;

$actualDate = date('Y-m-d');
$displayDate = $currentDate;

if ($currentDate && $currentDate < $actualDate) {
	$displayDate = $actualDate;
}

$priceChange = null;
$priceChangePct = null;

if ($currentPrice !== null && $previousPrice !== null && $previousPrice != 0) {
	$priceChange = round($currentPrice - $previousPrice, 4);
	$priceChangePct = round(($priceChange / $previousPrice) * 100, 2);
}

// 200 SMA
$sma200 = [];
$closeCount = count($eod_closes);

for ($i = 0; $i < $closeCount; $i++) {
	$window = array_slice($eod_closes, max(0, $i - 199), 200);
	if (count($window) === 200) {
		$sma200[] = round(array_sum($window) / 200, 2);
	} else {
		$sma200[] = null;
	}
}

$hasSma200 = count(array_filter($sma200, fn($v) => $v !== null)) > 30;
$sma200Json = $hasSma200
	? json_encode(array_reverse($sma200))
	: '[]';

require_once __DIR__ . '/../../engine/bewertungsmethoden/bewertung_oversold.php';
	
$ov_buy  = ($symbol ?? '') ? oversold_evaluate($symbol, ['direction' => 'buy'])  : null;
$ov_sell = ($symbol ?? '') ? oversold_evaluate($symbol, ['direction' => 'sell']) : null;

$status = 'neutral';
$badge  = 'secondary';
$info   = null;

if (is_array($ov_buy) && ($ov_buy['success'] ?? false) && ($ov_buy['signal'] ?? false)) {
	$status = 'unterkauft';
	$badge  = 'success';
	$info   = $ov_buy;
} elseif (is_array($ov_sell) && ($ov_sell['success'] ?? false) && ($ov_sell['signal'] ?? false)) {
	$status = 'überkauft';
	$badge  = 'danger';
	$info   = $ov_sell;
}

// === Whale-Patterns Daten unten anhängen ===
require_once __DIR__ . '/../../engine/bewertungsmethoden/bewertung_whale-patterns.php';

function _pct($v, $digits=2){ return is_numeric($v) ? number_format((float)$v, $digits, ',', '.') : '-'; }

if (!empty($symbol)) {
	$res = patterns_evaluate($symbol);
	if (empty($res['error'])) {
		$name   = (string)($res['name'] ?? '');
		$ex     = (string)($res['exchange'] ?? '');
		$score  = (int)round($res['score'] ?? 0);
		$signals= $res['signals'] ?? [];
		$weights= $res['weights'] ?? [];

		$ampelClass = ($score >= 70) ? 'bg-success' : (($score >= 40) ? 'bg-warning' : 'bg-danger');

		$labels = [
			'three_weeks_tight' => 'Three-Weeks-Tight',
			'flat_base'         => 'Flat Base',
			'high_tight_flag'   => 'High-Tight-Flag',
			'multiple_up_days'  => 'Mehrere Up-Days',
			'relative_strength' => 'Relative Stärke',
			'vol_dry_up'        => 'Volumen Dry-Up',
			'pivot_proximity'   => 'Nahe Pivot',
			'tight_closes'      => 'Tight Closes',
			'up_on_vol'         => 'Up on Volume',
			'down_on_low_vol'   => 'Down on Low Volume',
		];
		$explanations = [
			'three_weeks_tight' => 'Drei Wochen enge Handelsspanne nach starkem Anstieg.',
			'flat_base'         => 'Flache Basis (seitwärts) nach Anstieg.',
			'high_tight_flag'   => 'Sehr steiler Anstieg mit kurzer Flagge.',
			'multiple_up_days'  => 'Mehrere positive Tage mit höherem Close.',
			'relative_strength' => 'Preis relativ zum Benchmark (z. B. SPY) steigt und liegt über RS-SMA(50).',
			'vol_dry_up'        => 'Deutlich rückläufiges Volumen in der Konsolidierung.',
			'pivot_proximity'   => 'Kurs handelt nahe eines berechneten Pivot-Bereichs.',
			'tight_closes'      => 'Mehrere enge Schlusskurse in Folge.',
			'up_on_vol'         => 'Anstiege begleitet von erhöhtem Volumen.',
			'down_on_low_vol'   => 'Rückgänge bei vergleichsweise niedrigem Volumen.',
		];
	}
}
?>

<?php if (!empty($eod_dates)): ?>
<div class="row">
	<div class="col-6">
		<div class="d-flex align-items-center gap-2 alert bg-light text-dark py-2">
			<strong>Oversold/Overbought:</strong>
			<span class="badge bg-<?= $badge ?>"><?= htmlspecialchars($status) ?><?= $info ? ' ('.htmlspecialchars($info['score_label'] ?? '').')' : '' ?></span>
			<?php if ($info): ?>
				<span class="text-muted small">
				RSI14: <?= isset($info['details']['rsi14']) ? round((float)$info['details']['rsi14'],1) : '–' ?>,
				MOM63: <?= isset($info['details']['mom63']) ? round((float)$info['details']['mom63'],1) : '–' ?>%,
				<?= htmlspecialchars($info['details']['macd_mode'] ?? 'Kein MACD-Kriterium') ?>
				<?= !empty($info['details']['filterOK']) ? ', Filter OK' : '' ?>
				</span>
			<?php endif; ?>
		</div>
	</div>
	<div class="col-6">
		<div class="d-flex align-items-center gap-2 alert bg-light text-dark py-2">
			<strong>Whale Activity</strong>
			<span class="badge <?= $ampelClass ?>"><?= $score ?>/100</span>
		</div>
	</div>
	
	<div class="col-12 mt-2">
	<?php if ($currentPrice !== null && $priceChangePct !== null): ?>
		<div class="d-flex justify-content-between align-items-center mb-4">
			<div>
				<h5 class="mb-0"><strong><?= number_format($currentPrice, 2) ?> $</strong></h5>
				<small class="<?= $priceChange >= 0 ? 'text-success' : 'text-danger' ?>">
					(<?= $priceChange >= 0 ? '+' : '' ?><?= number_format($priceChange, 2) ?> $, <?= $priceChange >= 0 ? '+' : '' ?><?= $priceChangePct ?> %)
				</small>
				<small class="text-muted">
					<?= $currentDate ? 'vom ' . date('d.m.Y', strtotime($displayDate)) : '' ?>
				</small>
			</div>
			<select id="eodRangeSelect" class="form-select align-self-start" style="width: auto;">
				<option value="all">Alle</option>
				<option value="5y">5 Jahre</option>
				<option value="1y">1 Jahr</option>
				<option value="6m">6 Monate</option>
				<option value="3m">3 Monate</option>
				<option value="1m">1 Monat</option>
			</select>
		</div>
	<?php endif; ?>
		<div class="card">
			<div class="card-body">
				<h5 class="card-title">Kursverlauf Daily (<?= htmlspecialchars($symbol) ?>)</h5>
				<small id="performanceText" class="text-muted"></small>
				<canvas id="eodChart" height="80"></canvas>
			</div>
		</div>
	</div>
</div>
<div class="row mt-4">
	<div class="col-md-6">
		<div class="card">
			<div class="card-body">
				<h5 class="card-title">Drawdown in % (<?= htmlspecialchars($symbol) ?>)</h5>
				<canvas id="eodDrawdownChart" height="150" class="mt-4"></canvas>
			</div>
		</div>
	</div>
	<div class="col-md-6">
		<div class="card">
			<div class="card-body">
				<h5 class="card-title">Tages-Volatilität in % (<?= htmlspecialchars($symbol) ?>)</h5>
				<canvas id="eodVolatilityChart" height="150" class="mt-4"></canvas>
			</div>
		</div>
	</div>
</div>

<div class="row mt-4">
	<div class="col-12">
		<div class="card">
			<div class="card-body">
				<h5 class="card-title">ATR (Oversold) <span id="hintATR" class="small mb-1"></span></h5>
				<div style="height:350px;">
					<canvas id="eodATRChart"></canvas>
				</div>
			</div>
		</div>
	</div>
	<div class="col-12 mt-3">
		<div class="card">
			<div class="card-body">
				<h5 class="card-title">RSI (Oversold) <span id="hintRSI" class="small mb-1"></span></h5>
				<div style="height:350px;">
					<canvas id="eodRSIChart"></canvas>
				</div>
			</div>
		</div>
	</div>
	<div class="col-12 mt-3">
		<div class="card">
			<div class="card-body">
				<h5 class="card-title">Momentum (Oversold) <span id="hintMomentum" class="small mb-1"></span></h5>
				<div style="height:350px;">
					<canvas id="eodMomentumChart"></canvas>
				</div>
			</div>
		</div>
	</div>
</div>
		

<div class="row mt-4">
	<div class="col-12">
		<div class="card">
			<div class="card-body">
				<h2 class="h6 mb-2">
					<?= htmlspecialchars($symbol) ?> <?= $name ? '– '.htmlspecialchars($name) : '' ?>
					<?= $ex ? '<small>('.htmlspecialchars($ex).')</small>' : '' ?>
				</h2>

				<div class="d-flex justify-content-between align-items-center mt-3 mb-1">
					<strong>Whale Activity</strong>
					<span class="fw-semibold"><?= $score ?>/100</span>
				</div>
				<div class="progress" style="height:10px;">
					<div class="progress-bar <?= $ampelClass ?>" role="progressbar" style="width: <?= max(0,min(100,$score)) ?>%"></div>
				</div>

				<div class="table-responsive mt-4">
					<table class="table table-sm align-middle mb-0">
						<thead>
							<tr>
								<th>Signal</th>
								<th>OK</th>
								<th>Bewertung</th>
								<th>Details</th>
								<th>Erklärung</th>
							</tr>
						</thead>
						<tbody>
						<?php foreach ($labels as $key => $label):
							$s      = $signals[$key] ?? [];
							$ok     = (bool)($s['ok'] ?? false);
							$weight = (int)($weights[$key] ?? 0);
							$part   = isset($s['score']) ? (int)round($s['score']) : ($ok ? $weight : 0);

							// Details zusammenstellen
							$details = [];
							if (!empty($s['metrics']) && is_array($s['metrics'])){
								foreach ($s['metrics'] as $mk=>$mv){
									if (is_array($mv)) continue;
									$val = (strpos($mk,'pct')!==false) ? (_pct($mv,2).' %') : htmlspecialchars((string)$mv);
									$details[] = htmlspecialchars($mk).': '.$val;
								}
							}
							if (isset($s['ratio']))    $details[] = 'ratio: '.htmlspecialchars((string)$s['ratio']);
							if (isset($s['count']))    $details[] = 'count: '.htmlspecialchars((string)$s['count']);
							if (isset($s['lastDate'])) $details[] = 'last: '.htmlspecialchars((string)$s['lastDate']);
							?>
							<tr>
								<td><?= htmlspecialchars($label) ?></td>
								<td><?= $ok ? '<i class="fa fa-check-circle text-success"></i>' : '—' ?></td>
								<td><?= $part ?><?= $weight ? ' / '.$weight : '' ?></td>
								<td><?= $details ? implode(' · ', $details) : '' ?></td>
								<td class="small"><?= htmlspecialchars($explanations[$key] ?? '') ?></td>
							</tr>
						<?php endforeach; ?>
						</tbody>
					</table>
				</div>
			</div>
		</div>
	</div>
</div>


<script>
let eodChart = null;
let drawdownChart = null;
let volatilityChart = null;
let atrChart = null;
let rsiChart = null;
let momentumChart = null;

let fullEodDates   = <?= json_encode(array_reverse($eod_dates)) ?>;
let fullEodCloses  = <?= json_encode(array_reverse($eod_closes)) ?>;
let fullEodHighs   = <?= json_encode(array_reverse($eod_highs)) ?>;
let fullEodLows    = <?= json_encode(array_reverse($eod_lows)) ?>;
let sma200Full     = <?= $sma200Json ?>;

const crosshairPlugin = {
  id: 'crosshair',
  afterDraw(chart) {
	if (!chart.options?.plugins?.crosshair) return;
	const active = chart.getActiveElements ? chart.getActiveElements() : (chart._active || []);
	if (!active || active.length === 0) return;

	const { x, y } = active[0].element;
	const { left, right, top, bottom } = chart.chartArea;
	const ctx = chart.ctx;

	ctx.save();
	ctx.setLineDash([5, 5]);
	ctx.strokeStyle = 'rgba(0,0,0,0.5)';
	ctx.beginPath();
	ctx.moveTo(x, top);    ctx.lineTo(x, bottom);
	ctx.moveTo(left, y);   ctx.lineTo(right, y);
	ctx.stroke();
	ctx.restore();
  }
};

// Plugins nur einmal registrieren
if (window.Chart) {
  if (!window._techCrosshairReg) { Chart.register(crosshairPlugin); window._techCrosshairReg = true; }
  if (window['chartjs-plugin-annotation'] && !window._techAnnoReg) {
	Chart.register(window['chartjs-plugin-annotation']); window._techAnnoReg = true;
  }
}

// Helper
function destroyIf(x){ if (x && typeof x.destroy === 'function') { try{x.destroy();}catch(e){} } }

function filterEodData(range) {
  const now = new Date();
  switch (range) {
	case '1m': now.setMonth(now.getMonth() - 1); break;
	case '3m': now.setMonth(now.getMonth() - 3); break;
	case '6m': now.setMonth(now.getMonth() - 6); break;
	case '1y': now.setFullYear(now.getFullYear() - 1); break;
	case '5y': now.setFullYear(now.getFullYear() - 5); break;
	default: return {
	  dates: fullEodDates,
	  closes: fullEodCloses,
	  highs: fullEodHighs,
	  lows: fullEodLows
	};
  }

  const cutoff = now.toISOString().split('T')[0];
  const dates = [], closes = [], highs = [], lows = [];

  for (let i = 0; i < fullEodDates.length; i++) {
	if (fullEodDates[i] >= cutoff) {
	  dates.push(fullEodDates[i]);
	  closes.push(fullEodCloses[i]);
	  highs.push(fullEodHighs[i]);
	  lows.push(fullEodLows[i]);
	}
  }

  return { dates, closes, highs, lows };
}

function renderEodChart(range = 'all') {
  const canvas = document.getElementById('eodChart');
  if (!canvas) return;
  const ctx = canvas.getContext('2d');

  const { dates, closes, highs, lows } = filterEodData(range);

  // alle bestehenden Instanzen vor Neuaufbau zerstören
  destroyIf(eodChart); destroyIf(drawdownChart); destroyIf(volatilityChart);
  destroyIf(atrChart); destroyIf(rsiChart); destroyIf(momentumChart);
  eodChart = drawdownChart = volatilityChart = atrChart = rsiChart = momentumChart = null;

  // SMA200 filtern
  const sma200Filtered = [];
  const startIndex = fullEodDates.findIndex(d => d === dates[0]);
  if (startIndex !== -1) {
	for (let i = startIndex; i < startIndex + dates.length; i++) {
	  sma200Filtered.push(sma200Full[i] ?? null);
	}
  }

  const datasets = [
	{
	  label: 'Schlusskurs ($)',
	  data: closes,
	  borderColor: '#000',
	  borderWidth: 1.5,
	  tension: 0.1,
	  pointRadius: 0
	}
  ];

  if (sma200Filtered.filter(x => x !== null).length > 180) {
	const smaDataset = dates.map((d, i) => ({ x: d, y: sma200Filtered[i] }));
	datasets.push({
	  label: '200-Tage-Linie',
	  data: smaDataset,
	  borderColor: 'red',
	  borderWidth: 1.2,
	  tension: 0.2,
	  pointRadius: 0
	});
  }

  // Performance-Text aktualisieren
  const perfElem = document.getElementById('performanceText');
  if (closes.length >= 2 && perfElem) {
	const perf = ((closes.at(-1) - closes[0]) / closes[0]) * 100;
	const rounded = perf.toFixed(2);
	const prefix = perf >= 0 ? '+' : '';
	perfElem.className = 'text-muted';
	perfElem.innerHTML = `Performance im Zeitraum: <span class="${perf >= 0 ? 'text-success' : 'text-danger'}">${prefix}${rounded}%</span>`;
  }

  eodChart = new Chart(ctx, {
	type: 'line',
	data: { labels: dates, datasets },
	options: {
	  interaction: { mode: 'nearest', intersect: false },
	  scales: {
		x: { type: 'time', time: { unit: 'month' } },
		y: { beginAtZero: false }
	  },
	  plugins: { legend: { display: true }, crosshair: true }
	}
  });

  drawdownChart   = renderDrawdownChart(dates, closes);
  volatilityChart = renderVolatilityChart(dates, highs, lows, closes);
  atrChart        = renderATRChart(dates, highs, lows, closes);
  rsiChart        = renderRSIChart(dates, closes);
  momentumChart   = renderMomentumChart(dates, closes);
}

function renderDrawdownChart(dates, closes) {
  if (!dates.length || !closes.length) return;
  const ctx = document.getElementById('eodDrawdownChart')?.getContext('2d');
  if (!ctx) return;

  let peak = closes[0];
  const dd = closes.map(c => {
	if (c > peak) peak = c;
	return ((c - peak) / peak) * 100;
  });

  const maxDrawdownValue = Math.min(...dd).toFixed(2);
  const minDrawdown = Math.floor(Math.min(...dd));
  const maxDrawdown = Math.ceil(Math.max(...dd));
  const yMin = minDrawdown - 5;
  const yMax = Math.max(maxDrawdown, 0) + 5;

  drawdownChart = new Chart(ctx, {
	type: 'line',
	data: {
	  labels: dates,
	  datasets: [{
		label: 'Drawdown (%)',
		data: dd,
		borderColor: 'black',
		backgroundColor: 'rgba(0,0,0,0.1)',
		borderWidth: 1.5,
		fill: true,
		pointRadius: 0
	  }]
	},
	options: {
	  scales: {
		y: {
		  min: yMin,
		  max: yMax,
		  ticks: { callback: v => v.toFixed(0) + '%' }
		},
		x: { type: 'time', time: { unit: 'month' } }
	  },
	  plugins: {
		annotation: {
		  annotations: {
			maxDrawdownLine: {
			  type: 'line',
			  yMin: Math.min(...dd),
			  yMax: Math.min(...dd),
			  borderColor: 'red',
			  borderWidth: 1.5,
			  label: {
				enabled: true,
				content: `${maxDrawdownValue}%`,
				position: 'start',
				backgroundColor: 'rgba(255, 0, 0, 0.9)',
				color: 'white',
				font: { size: 10, weight: 'bold' }
			  }
			}
		  }
		}
	  }
	},
	plugins: [Chart.registry.getPlugin('annotation')]
  });
  return drawdownChart;
}

function renderVolatilityChart(dates, highs, lows, closes) {
  console.log('[VolatilityChart] Daten: ', { dates, highs, lows, closes });

  const ctx = document.getElementById('eodVolatilityChart')?.getContext('2d');
  if (!ctx) return;

  const vola = highs.map((h, i) => {
	const low = lows[i];
	const close = closes[i];
	if (typeof h === 'number' && typeof low === 'number' && typeof close === 'number' && close !== 0) {
	  return ((h - low) / close) * 100;
	}
	return null;
  });

  const validVola = vola.filter(v => typeof v === 'number');
  const avg = validVola.length > 0 ? validVola.reduce((a, b) => a + b, 0) / validVola.length : null;

  console.log('[VolatilityChart] Relative Vola (%):', vola);
  console.log('[VolatilityChart] Durchschnitt (%):', avg);

  volatilityChart = new Chart(ctx, {
	type: 'bar',
	data: {
	  labels: dates,
	  datasets: [{
		label: 'Tages-Volatilität in %',
		data: vola,
		backgroundColor: 'black',
		barThickness: 1
	  }]
	},
	options: {
	  scales: {
		y: {
		  beginAtZero: true,
		  ticks: { callback: v => v.toFixed(1) + ' %' }
		},
		x: { type: 'time', time: { unit: 'month' } }
	  },
	  plugins: {
		legend: { display: true },
		annotation: {
		  annotations: avg !== null ? {
			avgLine: {
			  type: 'line',
			  yMin: avg, yMax: avg,
			  borderColor: 'red', borderWidth: 1,
			  label: {
				content: `Ø ${avg.toFixed(2)} %`,
				enabled: true, position: 'start',
				backgroundColor: 'rgba(255, 0, 0, 0.9)',
				color: 'white', font: { size: 10, weight: 'bold' }
			  }
			}
		  } : {}
		}
	  }
	}
  });
  return volatilityChart;
}

function atr(highs,lows,closes,p=14){
  const tr=[]; for(let i=0;i<closes.length;i++){
	const prev=closes[i-1]??closes[i];
	const a=highs[i]-lows[i], b=Math.abs(highs[i]-prev), c=Math.abs(lows[i]-prev);
	tr.push(Math.max(a,b,c));
  }
  const atr=[]; let sum=0;
  for(let i=0;i<tr.length;i++){
	if(i<p) { sum+=tr[i]; atr.push(null); }
	else if(i===p){ sum+=tr[i]; atr.push(sum/p); }
	else { atr.push((atr[i-1]*(p-1)+tr[i])/p); }
  }
  return atr;
}

function lastNum(arr){
  for(let i=arr.length-1;i>=0;i--) if(Number.isFinite(arr[i])) return arr[i];
  return null;
}
function setHint(elId, label, state){
  const el = document.getElementById(elId); if(!el) return;
  const map = { neutral:'text-muted', overbought:'text-danger', oversold:'text-success',
				high:'text-danger', low:'text-primary', normal:'text-muted' };
  el.className = `small mb-1 ${map[state]||'text-muted'}`;
  el.textContent = `${label}: ${state}`;
}

function renderATRChart(dates, highs, lows, closes){
  const c = document.getElementById('eodATRChart'); if(!c) return;
  c.height = 120;
  const ctx = c.getContext('2d');

  const a = atr(highs,lows,closes,14).map((v,i)=>v&&closes[i]? (v/closes[i])*100:null);
  const vals = a.filter(v => Number.isFinite(v));
  const avg = vals.length ? vals.reduce((x,y)=>x+y,0)/vals.length : null;
  const sorted = [...vals].sort((x,y)=>x-y);
  const p75 = sorted.length ? sorted[Math.floor(0.75*(sorted.length-1))] : null;

  const aVal = lastNum(a);
  let volaState = 'normal';
  if (aVal!=null && p75!=null && avg!=null){
	const p25 = vals.length ? vals[Math.floor(0.25*(vals.length-1))] : null;
	volaState = p25!=null ? (aVal>p75?'high': (aVal<p25?'low':'normal')) : (aVal>avg?'high':'normal');
  }
  setHint('hintATR', 'Volatilität (ATR% 14)', volaState);

  const chart = new Chart(ctx,{
	type:'line',
	data:{ labels:dates, datasets:[{ label:'ATR(14) %', data:a, borderWidth:1.2, borderColor:'#000', pointRadius:0 }]},
	options:{
	  maintainAspectRatio:false,
	  scales:{ x:{ type:'time', time:{ unit:'month'}}, y:{ beginAtZero:true }},
	  plugins:{
		legend:{ display:true },
		annotation:{
		  annotations:{
			...(avg!==null ? { atrAvg:{type:'line', yMin:avg, yMax:avg, borderWidth:1, borderColor:'red',
			  label:{enabled:true, content:`Ø ${avg.toFixed(2)} %`, position:'start'}} } : {}),
			...(p75!==null ? { atrP75:{type:'line', yMin:p75, yMax:p75, borderWidth:1, borderColor:'black',
			  label:{enabled:true, content:`P75 ${p75.toFixed(2)} %`, position:'end'}} } : {})
		  }
		}
	  }
	}
  });
  return chart;
}

function rsi(closes,p=14){
  const r=[]; let ga=0,gl=0;
  for(let i=1;i<closes.length;i++){
	const ch=closes[i]-closes[i-1], up=Math.max(ch,0), dn=Math.max(-ch,0);
	if(i<=p){ ga+=up; gl+=dn; r.push(null); if(i===p){ ga/=p; gl/=p; } }
	else { ga=(ga*(p-1)+up)/p; gl=(gl*(p-1)+dn)/p; const rs=gl===0?100:100-(100/(1+ga/gl)); r.push(rs); }
  }
  return [null,...r];
}
function renderRSIChart(dates, closes){
  const c = document.getElementById('eodRSIChart'); if(!c) return;
  c.height = 120;
  const ctx = c.getContext('2d');

  const data = rsi(closes,14);
  const rsiVal = lastNum(data);
  const rsiState = rsiVal==null ? 'neutral' : (rsiVal>70?'overbought': (rsiVal<30?'oversold':'neutral'));
  setHint('hintRSI', 'RSI(14)', rsiState);

  const chart = new Chart(ctx,{
	type:'line',
	data:{ labels: dates, datasets:[{ label:'RSI(14)', data: data, borderColor:'#000', borderWidth:1.2, pointRadius:0 }]},
	options:{ responsive: true, maintainAspectRatio:false, scales:{ y:{ min:0, max:100 }}, plugins:{ legend:{ display:true }, annotation:{ annotations:{
	  rsi70:{ type:'line', yMin:70, yMax:70, borderColor:'red', borderWidth:1 },
	  rsi30:{ type:'line', yMin:30, yMax:30, borderColor:'red', borderWidth:1 }
	}}}}
  });
  return chart;
}

function momentumPct(closes,lb=63){
  const out=Array(closes.length).fill(null);
  for(let i=lb;i<closes.length;i++){
	const base=closes[i-lb]; if(base) out[i]=((closes[i]-base)/base)*100;
  }
  return out;
}
function renderMomentumChart(dates, closes){
  const c = document.getElementById('eodMomentumChart'); if(!c) return;
  c.height = 120;
  const ctx = c.getContext('2d');

  const m = momentumPct(closes,63);
  const mVal = lastNum(m);
  const mState = mVal==null ? 'neutral' : (mVal>20?'overbought': (mVal<-20?'oversold':'neutral'));
  setHint('hintMomentum', 'Momentum 63d %', mState);

  const chart = new Chart(ctx,{
	type:'line',
	data:{ labels:dates, datasets:[{ label:'Momentum 63d %', data:m, borderWidth:1.2, borderColor:'#000', pointRadius:0 }]},
	options:{
	  responsive: true, maintainAspectRatio:false,
	  scales:{ x:{ type:'time', time:{ unit:'month'}}, y:{ beginAtZero:false }},
	  plugins:{
		legend:{ display:true },
		annotation:{ annotations:{
		  zero:{ type:'line', yMin:0,  yMax:0,  borderWidth:1, borderColor:'black', label:{enabled:true, content:'0 %', position:'start'} },
		  up20:{ type:'line', yMin:20, yMax:20, borderWidth:1, borderColor:'red',   label:{enabled:true, content:'+20 %', position:'end'} },
		  dn20:{ type:'line', yMin:-20,yMax:-20,borderWidth:1, borderColor:'red',   label:{enabled:true, content:'-20 %', position:'end'} }
		}}
	  }
	}
  });
  return chart;
}

let techInitDone = false;
document.addEventListener('ajaxTabLoaded', (e) => {
  if (!e.detail || e.detail.targetId !== '#tab-technical') return;
  if (techInitDone) return;
  techInitDone = true;

  console.log('[DEBUG] ajaxTabLoaded erkannt – initialisiere Kurschart');

  const rangeSelect = document.getElementById('eodRangeSelect');
  rangeSelect?.addEventListener('change', () => {
	renderEodChart(rangeSelect.value);
  });

  renderEodChart(rangeSelect?.value || '6m');
});

// Resize beim Tab-Wechsel
document.addEventListener('shown.bs.tab', () => {
  [eodChart, drawdownChart, volatilityChart, atrChart, rsiChart, momentumChart]
	.forEach(ch => { if (ch && ch.resize) ch.resize(); });
});
</script>

<?php endif; ?>