<?php

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
	echo "ERROR|–|–|Dieses Skript muss per POST aufgerufen werden\n";
	flush();
	exit;
}

//while (ob_get_level()) ob_end_clean();
//ob_implicit_flush(true);

header('Content-Type: text/plain; charset=utf-8');

ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);

require_once '../../engine/engine.php';
require_once '../../engine/api-handling/api_helpers.php';

$sourceFile  = $_POST['source_file'] ?? '';
$startIndex  = max(0, (int)($_POST['start_index'] ?? 0));
$limitCount  = min(100, max(1, (int)($_POST['limit_count'] ?? 50)));
$pauseSec    = max(0, (float)($_POST['pause_sec'] ?? 0.2));
$method      = $_POST['method'] ?? 'fundamentale-kriterien';
$scanId      = $_POST['scan_id'] ?? null;

$apiKey      = $FmpApiKey;

if (!$scanId || !preg_match('/^scan_/', $scanId)) {
	echo "ERROR|–|–|Ungültige Scan-ID\n";
	flush();
	exit;
}

if (!empty($_POST['chunk']) && empty($_POST['tickers_json'])) {
	$_POST['tickers_json'] = $_POST['chunk'];
}
if (!empty($_POST['tickers_json'])) {
	$tickerData = json_decode($_POST['tickers_json'], true);
} else {
	$filePath = realpath(__DIR__ . '/../tickers/ticker-listen/' . basename($sourceFile));
	if (!$filePath || !is_file($filePath)) {
		echo "ERROR|–|–|Dateifehler: '$sourceFile' ist keine gültige Datei\n";
		flush();
		exit;
	}
	$json = file_get_contents($filePath);
	$tickerData = json_decode($json, true);
}

if (!is_array($tickerData) || count($tickerData) === 0) {
	echo "ERROR|–|–|Keine gültigen Ticker vorhanden\n";
	flush();
	exit;
}

$tickersToScan = array_slice($tickerData, $startIndex, $limitCount);
if (count($tickersToScan) === 0) {
	echo "ERROR|–|–|Keine Ticker im aktuellen Chunk\n";
	flush();
	exit;
}

$moduleFile = __DIR__ . "/bewertungsmethoden/scoring_{$method}.php";
if (!file_exists($moduleFile)) {
	echo "ERROR|–|–|Modul für Methode '$method' nicht gefunden\n";
	flush();
	exit;
}
require_once $moduleFile;

if (!function_exists('run_scoring')) {
	echo "ERROR|–|–|Modul '$method' enthält keine Funktion run_scoring()\n";
	flush();
	exit;
}

$params = [
	'apiKey'        => $apiKey,
	'scanId'        => $scanId,
	'minScore'      => (int)($_POST['min_score_percent'] ?? 50),
	'direction'     => $_POST['oversold_direction'] ?? 'buy',
	'saison_months' => (int)($_POST['saison_months'] ?? 3),
	'pdo'           => $pdo,
];
if ($method === 'saisonalitaet100') {
	$params['minScore'] = (int)($_POST['threshold_percent'] ?? 100);
}
if ($method === 'minervini') {
	$params['scoreMin'] = (int)($_POST['score_min'] ?? 10);
}
if ($method === 'strategic-profiles') {
	$params['profile'] = $_POST['strategic-profile'] ?? 'high_performer';
}
if ($method === 'chart-whale-patterns') {
	$params['min_score_whales'] = (int)($_POST['min_score_whales'] ?? 80);
	$params['lookback_bars']  = (int)($_POST['lookback_bars'] ?? 260);
	$params['benchmark']      = $_POST['benchmark'] ?? 'SPY';
}

$chunkSymbols = array_map(function($t) {
	$sym = is_array($t) ? ($t['symbol'] ?? $t['Code'] ?? '') : $t;
	return strtoupper(trim($sym));
}, $tickersToScan);
sort($chunkSymbols);
$chunkHash = md5(implode(',', $chunkSymbols));

$stmt = $pdo->prepare("SELECT COUNT(*) FROM scan_chunks WHERE scan_id = ? AND chunk_hash = ?");
$stmt->execute([$scanId, $chunkHash]);
$alreadyProcessed = (int)$stmt->fetchColumn() > 0;

if ($alreadyProcessed) {
	echo "SKIP|–|–|Chunk bereits verarbeitet, überspringe.\n";
	flush();
	exit;
}

try {
	echo "SCANID|$scanId\n";
	echo str_repeat(" ", 2048) . "\n";
	if (ob_get_level() > 0) @ob_flush();
	flush();
	
	$results = run_scoring($tickersToScan, $params);
	
	if (!empty($results['data']) && is_array($results['data'])) {
		$upsert = $pdo->prepare("
			INSERT INTO scan_results
				(scan_id, ticker, name, exchange, score, method)
			VALUES
				(:scan_id, :ticker, :name, :exchange, :score, :method)
			ON DUPLICATE KEY UPDATE
				scan_id  = VALUES(scan_id),
				name     = VALUES(name),
				exchange = VALUES(exchange),
				score    = VALUES(score)
		");
	
		// lokale Entdoppelung, plus Normalisierung
		$seen = [];
		foreach ($results['data'] as $entry) {
			$ticker = strtoupper(trim($entry['ticker'] ?? ''));
			if ($ticker === '') continue;
	
			$meth = trim((string)($entry['method'] ?? $method));
			$k = $ticker . '|' . $meth;
			if (isset($seen[$k])) continue;
			$seen[$k] = true;
	
			$upsert->execute([
				':scan_id'  => $scanId,
				':ticker'   => $ticker,
				':name'     => $entry['name'] ?? '',
				':exchange' => $entry['exchange'] ?? '',
				':score'    => (float)($entry['score'] ?? 0),
				':method'   => $meth,
			]);
		}
	}

	foreach ($results['messages'] ?? [] as $line) {
		echo $line . "\n";
		flush();
	}

	$scannedCount  = $results['scanned'] ?? count($tickersToScan);
	$successCount  = $results['hits'] ?? 0;
	$durationSec   = round(microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"], 1);
	
	echo "CHECK|–|–|Scan abgeschlossen: $successCount Treffer bei $scannedCount Tickern.\n";
	echo "DONE|$scannedCount|$successCount|{$durationSec} Sekunden\n";
	
	try {
		$upd = $pdo->prepare("
			UPDATE scan_meta
			SET scanned_total = scanned_total + :scanned,
				hits_total    = hits_total    + :hits
			WHERE scan_id = :scan_id
		");
		$upd->execute([':scanned'=>$scannedCount, ':hits'=>$successCount, ':scan_id'=>$scanId]);
	} catch (PDOException $e) {
		$upd2 = $pdo->prepare("
			UPDATE scan_meta
			SET scanned_total = scanned_total + :scanned
			WHERE scan_id = :scan_id
		");
		$upd2->execute([':scanned'=>$scannedCount, ':scan_id'=>$scanId]);
	}
	
	$isLastChunk = (($_POST['chunkIndex'] ?? 0) == ($_POST['chunkTotal'] ?? -1));
	
	if ($isLastChunk) {
		// letzter Chunk → Marker-Tabelle aufräumen
		$pdo->prepare("DELETE FROM scan_chunks WHERE scan_id = ?")
			->execute([$scanId]);
	} else {
		// nur wenn nicht letzter Chunk → Marker für diesen Chunk setzen
		$pdo->prepare("
			INSERT IGNORE INTO scan_chunks (scan_id, chunk_hash)
			VALUES (?, ?)
		")->execute([$scanId, $chunkHash]);
	}
	
	flush();
} catch (Throwable $e) {
	echo "ERROR|–|–|Exception: {$e->getMessage()}\n";
	flush();
}