<?php
/**
 * scoring_saisonalitaet100.php
 * Contract & Stil wie scoring_saisonalitaet.php:
 *   - run_scoring(array $tickers, array $params): array
 *   - schreibt Treffer selbst in scan_results
 *   - liefert messages, hits, scanned zurück
 */

require_once __DIR__ . '/../../../engine/bewertungsmethoden/bewertung_saisonalitaet.php';
if (!function_exists('fmp_multi')) {
	require_once __DIR__ . '/../../../engine/api-handling/fmp_client.php';
}

/**
 * Baut eine robuste Map SYMBOL => Profil aus fmp_multi('profile', $symbols).
 * Akzeptiert verschiedene Rückgabeformen (assoziativ, Liste, verschachtelt).
 */
function _buildProfileMap(array $symbols): array {
	if (!function_exists('fmp_multi') || empty($symbols)) return [];

	try {
		$raw = fmp_multi('profile', $symbols);
	} catch (\Throwable $e) {
		return [];
	}

	$map = [];

	$addItem = function ($item) use (&$map) {
		if (!is_array($item)) return;
		$sym = strtoupper(trim((string)($item['symbol'] ?? $item['ticker'] ?? '')));
		if ($sym === '') return;
		$map[$sym] = $item;
	};

	if (is_array($raw)) {
		// Fall 1: Map symbol => item
		$looksLikeMap = false;
		foreach ($raw as $k => $v) {
			if (is_string($k)) { $looksLikeMap = true; break; }
		}
		if ($looksLikeMap) {
			foreach ($raw as $k => $v) {
				if (is_array($v)) {
					// Einige Helper legen das Profil als Array oder als Liste [0=>…] ab
					if (isset($v['symbol']) || isset($v['ticker'])) {
						$addItem($v);
					} elseif (isset($v[0]) && is_array($v[0])) {
						$addItem($v[0]);
					}
				}
			}
		} else {
			// Fall 2: Liste von Items
			foreach ($raw as $v) {
				if (is_array($v)) {
					$addItem($v);
				} elseif (is_array($v) && isset($v[0]) && is_array($v[0])) {
					$addItem($v[0]);
				}
			}
		}
	}

	return $map;
}

/** Felder extrahieren (Name/Exchange) aus einem Profil-Item */
function _extractNameExchangeFromProfile(array $p): array {
	$name = (string)($p['companyName'] ?? $p['name'] ?? $p['company_name'] ?? '');
	$ex   = (string)($p['exchangeShortName'] ?? $p['primaryExchange'] ?? $p['exchange'] ?? '');
	return [trim($name), trim($ex)];
}


function run_scoring(array $tickers, array $params): array
{
	/** @var PDO $pdo */
	$pdo    = $params['pdo'];
	$scanId = $params['scanId'];

	$minScore = isset($params['minScore'])
		? (int)$params['minScore']
		: (int)($_POST['threshold_percent'] ?? 100);

	// Monate/Optionen (UI -> Defaults greift in Bewertungsfunktion)
	$months = [];
	$months = array_values(array_unique(array_filter(
		array_map(fn($m) => (int)$m, $months),
		fn($m) => $m >= 1 && $m <= 12
	)));
	$opts['months'] = $months;
	if (isset($_POST['months']))     $months = array_map('intval', (array)$_POST['months']);
	if (empty($months) && isset($_POST['months[]'])) $months = array_map('intval', (array)$_POST['months[]']);

	$opts = [
		'months'            => $months,
		'threshold_percent' => isset($_POST['threshold_percent']) ? (int)$_POST['threshold_percent'] : $minScore,
		'min_years'         => isset($_POST['min_years']) ? (int)$_POST['min_years'] : 7,
		'direction'         => $_POST['direction'] ?? ($_POST['season_direction'] ?? 'long'),
		'max_years_back'    => isset($_POST['max_years_back']) ? (int)$_POST['max_years_back'] : 20,
	];
	$yearsBack = (int)($opts['max_years_back'] ?? 20);

	// Upserts wie gehabt
	$stmtScan = $pdo->prepare("
		INSERT INTO scan_results (scan_id, ticker, exchange, name, score, data_json, method)
		VALUES (?, ?, ?, ?, ?, ?, 'saisonalitaet100')
		ON DUPLICATE KEY UPDATE
			scan_id  = VALUES(scan_id),
			name     = VALUES(name),
			exchange = VALUES(exchange),
			score    = VALUES(score),
			data_json= VALUES(data_json),
			method   = VALUES(method)
	");

	// Zusatz-Logging in saisonale_aktien (falls du das schon eingebaut hast)
	$stmtSeason = $pdo->prepare("
		INSERT INTO saisonale_aktien
			(scan_id, ticker, name, exchange,
			 best_month, best_winrate, qualified_months,
			 threshold_percent, min_years, direction, years_back,
			 data_json)
		VALUES
			(:scan_id, :ticker, :name, :exchange,
			 :best_month, :best_winrate, :qualified_months,
			 :threshold_percent, :min_years, :direction, :years_back,
			 :data_json)
		ON DUPLICATE KEY UPDATE
			scan_id           = VALUES(scan_id),
			name              = VALUES(name),
			exchange          = VALUES(exchange),
			best_month        = VALUES(best_month),
			best_winrate      = VALUES(best_winrate),
			qualified_months  = VALUES(qualified_months),
			threshold_percent = VALUES(threshold_percent),
			min_years         = VALUES(min_years),
			direction         = VALUES(direction),
			years_back        = VALUES(years_back),
			data_json         = VALUES(data_json),
			created_at        = NOW()
	");
	
	// --- Profile einmalig für alle Symbole laden (falls verfügbar) ---
	$symbolsForProfile = [];
	foreach ($tickers as $t2) {
		$s2 = is_array($t2) ? ($t2['symbol'] ?? $t2['Code'] ?? $t2['Ticker'] ?? $t2['Symbol'] ?? '') : $t2;
		$s2 = strtoupper(trim((string)$s2));
		if ($s2 !== '') $symbolsForProfile[] = $s2;
	}
	$profileMap = [];
	if (function_exists('fmp_multi') && $symbolsForProfile) {
		try {
			$profileMap = fmp_multi('profile', $symbolsForProfile);
		} catch (\Throwable $e) {
			$profileMap = [];
		}
	}
	// Fallback-Metadaten aus der Tickerliste (Name/Exchange), wie in scoring_saisonalitaet.php
	$fallbackMeta = [];
	foreach ($tickers as $entry) {
		$s = is_array($entry) ? ($entry['symbol'] ?? $entry['Code'] ?? '') : $entry;
		$s = strtoupper(trim((string)$s));
		if ($s === '') continue;
		$fallbackMeta[$s] = [
			'name'     => is_array($entry) ? ($entry['name'] ?? $entry['Name'] ?? '') : '',
			'exchange' => is_array($entry) ? ($entry['exchangeShortName'] ?? $entry['Exchange'] ?? '') : '',
		];
	}

	$messages = [];
	$hits     = 0;
	$scanned  = 0;

	foreach ($tickers as $t) {
		// Rohdaten aus der Liste (als Fallback)
		$rawSym = is_array($t) ? ($t['symbol'] ?? $t['Code'] ?? $t['Ticker'] ?? $t['Symbol'] ?? '') : $t;
		$symbol = strtoupper(trim((string)$rawSym));
		if ($symbol === '') continue;

		$nameFromList = is_array($t) ? (
			$t['name'] ?? $t['companyName'] ?? $t['Company'] ?? $t['Title'] ?? ''
		) : '';
		$exchFromList = is_array($t) ? (
			$t['exchange'] ?? $t['exchangeShortName'] ?? $t['primaryExchange'] ?? $t['Exchange'] ?? ''
		) : '';

		$scanned++;

		// Bewertung ausführen
		$r = bewertung_saisonalitaet_100($symbol, $opts);

		$scorePercent = (int)($r['score_percent'] ?? 0);
		$label        = (string)($r['score_label'] ?? '--');

		// --- Name/Exchange wie in der klassischen Saisonalität befüllen ---
		$name     = '';
		$exchange = '';
		
		try {
			$meta = compute_seasonality($symbol, [
				'scope'         => 'last',
				'years'         => $yearsBack,     // nutzt denselben Zeitraum
				'serietype'     => 'line',
				'with_segments' => false,
			]);
			$name     = (string)($r['name']     ?? '');
			$exchange = (string)($r['exchange'] ?? '');
			
			if ($name === '' && $nameFromList !== '' && strtoupper($nameFromList) !== $symbol) $name = $nameFromList;
			if ($exchange === '' && $exchFromList !== '') $exchange = $exchFromList;
			
			// Wenn exchange noch leer ist: wie Fundamental -> profile, dann quote
			if ($exchange === '') {
				try {
					$multi = fmp_multi([
						'profile' => ['key' => 'profile', 'vars' => ['symbol' => $symbol]],
						'quote'   => ['key' => 'quote',   'vars' => ['symbol' => $symbol]],
					]);
			
					// profile
					$pArr = $multi['profile'] ?? [];
					$p    = (is_array($pArr) && isset($pArr[0])) ? $pArr[0] : (is_array($pArr) ? $pArr : []);
					if (is_array($p)) {
						if ($exchange === '' && !empty($p['exchangeShortName'])) $exchange = (string)$p['exchangeShortName'];
						if ($exchange === '' && !empty($p['exchange']))          $exchange = (string)$p['exchange'];
						if (($name === '' || strtoupper($name) === $symbol) && !empty($p['companyName'])) {
							$name = (string)$p['companyName'];
						}
					}
			
					// quote-Fallback
					if ($exchange === '') {
						$qArr = $multi['quote'] ?? [];
						$q    = (is_array($qArr) && isset($qArr[0])) ? $qArr[0] : (is_array($qArr) ? $qArr : []);
						if (is_array($q)) {
							if ($exchange === '' && !empty($q['primaryExchange'])) $exchange = (string)$q['primaryExchange'];
							if ($exchange === '' && !empty($q['stockExchange']))   $exchange = (string)$q['stockExchange'];
							if ($exchange === '' && !empty($q['exchange']))        $exchange = (string)$q['exchange'];
						}
					}
				} catch (\Throwable $e) {}
			}
			
			// niemals Ticker als Name speichern
			if ($name === $symbol) $name = '';

		} catch (\Throwable $e) {
			// ignoriere – wir haben noch Fallback(s)
		}
		
		if (($name === '' || $exchange === '') && function_exists('fmp_multi')) {
			try {
				$pm = fmp_multi('profile', [$symbol]);
				$p  = $pm[$symbol] ?? (is_array($pm) ? reset($pm) : null);
				if (is_array($p)) {
					if ($name === '' && !empty($p['companyName']))           $name = $p['companyName'];
					if ($exchange === '' && !empty($p['exchangeShortName'])) $exchange = $p['exchangeShortName'];
					if ($exchange === '' && !empty($p['exchange']))          $exchange = $p['exchange'];
				}
			} catch (\Throwable $ignore) {}
		}
		
		// niemals Symbol als Name zurückgeben
		if (strtoupper($name) === strtoupper($symbol)) $name = '';
		if (strcasecmp($name, $symbol) === 0) { $name = ''; }

		// Debug-/Konsolenzeile
		$messages[] = "CHECK|{$symbol}|–|{$label}|{$symbol}|saisonalitaet100";

		// Treffer?
		$qualified = (array)($r['data']['qualified_months'] ?? []);
		if ($scorePercent >= $minScore && !empty($qualified)) {
			$hits++;

			// Daten für Inserts
			$dataJson = json_encode([
				'score_label'       => $label,
				'threshold_percent' => (int)($opts['threshold_percent'] ?? $minScore),
				'months_selected'   => (array)($opts['months'] ?? []),
				'min_years'         => (int)($opts['min_years'] ?? 7),
				'direction'         => (string)($opts['direction'] ?? 'long'),
				'years_by_month'    => (array)($r['data']['years_by_month'] ?? []),
				'winrates_percent'  => (array)($r['data']['winrates_percent'] ?? []),
				'qualified_months'  => (array)$qualified,
			], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);

			// scan_results
			$stmtScan->execute([$scanId, $symbol, $exchange, $name, $scorePercent, $dataJson]);

			// saisonale_aktien (falls aktiv)
			if ($stmtSeason) {
				// besten Monat & Winrate bestimmen
				$winrates  = (array)($r['data']['winrates_percent'] ?? []);
				$bestMonth = null; $bestWin = null;
				foreach ((array)$qualified as $m) {
					$w = isset($winrates[$m]) ? (int)$winrates[$m] : null;
					if ($w === null) continue;
					if ($bestWin === null || $w > $bestWin) { $bestWin = $w; $bestMonth = (int)$m; }
				}
				$stmtSeason->execute([
					':scan_id'           => $scanId,
					':ticker'            => $symbol,
					':name'              => $name,
					':exchange'          => $exchange,
					':best_month'        => $bestMonth,
					':best_winrate'      => $bestWin ?? $scorePercent,
					':qualified_months'  => implode(',', array_map('intval', (array)$qualified)),
					':threshold_percent' => (int)($opts['threshold_percent'] ?? $minScore),
					':min_years'         => (int)($opts['min_years'] ?? 7),
					':direction'         => (string)($opts['direction'] ?? 'long'),
					':years_back'        => (int)($opts['max_years_back'] ?? 20),
					':data_json'         => $dataJson,
				]);
			}
		}
	}

	return [
		'messages' => $messages,
		'hits'     => $hits,
		'scanned'  => $scanned,
	];
}
