<?php
declare(strict_types=1);

/**
 * Bewertungslogik Fundamental
 * Liefert nur den Score (und Total/Percent), optional mit Detailflags.
 *
 * Usage:
 *   require_once __DIR__ . '/../api-handling/fmp_client.php';
 *   require_once __DIR__ . '/bewertungsmethoden/bewertung_fundamental.php';
 *   $res = bewertung_fundamental_score('AAPL', '2024-08-01');
 *   // $res = ['score'=>.., 'total'=>.., 'percent'=>.., 'details'=>[...]]
 */

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

/** Fallback-SECTOR KGV */
const SECTOR_DEFAULT_PE = [
	'Technology'            => 25,
	'Healthcare'            => 18,
	'Financial Services'    => 12,
	'Industrials'           => 15,
	'Utilities'             => 13,
	'Energy'                => 10,
	'Consumer Defensive'    => 16,
	'Consumer Cyclical'     => 18,
	'Communication Services'=> 17,
	'Real Estate'           => 14,
	'Basic Materials'       => 13,
];

/** ---------- Kleine Helper (tristate: true/false/null) ---------- */
function c_gt($v, float $min) { return is_numeric($v) ? ((float)$v > $min) : null; }
function c_lt($v, float $max) { return is_numeric($v) ? ((float)$v < $max) : null; }
function c_between($v, float $min, float $max) { return is_numeric($v) ? ((float)$v > $min && (float)$v < $max) : null; }
function c_and($a, $b) { return ($a === null || $b === null) ? null : ($a && $b); }
function c_price_below($price, $fv) {
	if (!is_numeric($price) || !is_numeric($fv)) return null;
	return ((float)$price) < ((float)$fv);
}
function add_point(?bool $cond, int &$score, int &$total, array &$details, string $key) {
	if ($cond === null) { $details[$key] = null; return; }
	$total += 1;
	if ($cond) $score += 1;
	$details[$key] = $cond;
}

/** Wählt passenden Eintrag ≤ asof, sonst jüngsten */
function pick_entry_by_date(array $rows, ?string $asof): array {
	if (empty($rows)) return [];
	usort($rows, fn($a,$b) => strtotime($b['date'] ?? '') <=> strtotime($a['date'] ?? ''));
	if (!$asof) return $rows[0] ?? [];
	$asTs = strtotime($asof);
	$best = null;
	foreach ($rows as $r) {
		if (!isset($r['date'])) continue;
		$ts = strtotime($r['date']);
		if ($ts <= $asTs) {
			if ($best === null || $ts > strtotime($best['date'])) $best = $r;
		}
	}
	return $best ?? ($rows[0] ?? []);
}

/** Lädt Minimaldaten für Scoring (TTM + Key Metrics + Growth + Quote) */
function bewertung_fundamental_fetch_data(string $symbol, ?string $asof = null): array {
	$symbol = strtoupper(trim($symbol));
	$useHistorical = !empty($asof);

	// Basisendpunkte (kompatibel zu deinem Tab)
	$multi1 = fmp_multi([
		'profile' => [
			'key'=>'profile',
			'vars'=>['symbol'=>$symbol]
		],
		'metrics' => [
			'key'=>'key_metrics',
			'vars'=>['symbol'=>$symbol],
			'query'=>$useHistorical ? ['limit'=>120] : ['limit'=>1]
		],
		'ratios'  => $useHistorical
			? ['key'=>'ratios','vars'=>['symbol'=>$symbol],'query'=>['period'=>'quarter','limit'=>40]]
			: ['key'=>'ratios_ttm','vars'=>['symbol'=>$symbol]],
		'growth'  => [
			'key'=>'financial_growth'
			,'vars'=>['symbol'=>$symbol]
		],
		'quote'   => [
			'key'=>'quote',
			'vars'=>['symbol'=>$symbol]
		]
	]);

	$profileArr = $multi1['profile'] ?? [];
	$metricsArr = $multi1['metrics'] ?? [];
	$ratiosArr  = $multi1['ratios']  ?? [];
	$growthArr  = $multi1['growth']  ?? [];
	$quoteArr   = $multi1['quote']   ?? [];

	$profile = is_array($profileArr) && isset($profileArr[0]) ? $profileArr[0] : (is_array($profileArr) ? $profileArr : []);
	$metrics = is_array($metricsArr) && isset($metricsArr[0]) ? ($useHistorical ? pick_entry_by_date($metricsArr, $asof) : $metricsArr[0]) : [];
	if ($useHistorical && is_array($ratiosArr) && isset($ratiosArr[0])) {
		$ratios = pick_entry_by_date($ratiosArr, $asof);
	} else {
		$ratios = is_array($ratiosArr) && isset($ratiosArr[0]) ? $ratiosArr[0] : (is_array($ratiosArr) ? $ratiosArr : []);
	}
	$growth  = is_array($growthArr) ? pick_entry_by_date(is_array($growthArr) && isset($growthArr[0]) ? $growthArr : [$growthArr], $asof) : [];
	$quote0  = is_array($quoteArr)  && isset($quoteArr[0])  ? $quoteArr[0]  : (is_array($quoteArr)  ? $quoteArr  : []);

	// Ableitungen
	$sector = $profile['sector'] ?? null;
	$price  = $profile['price'] ?? ($quote0['price'] ?? null);

	// Daten-Mapping – 25 Kriterien
	$data = [
		'sector'                   => $sector,
		'price'                    => $price,
		'pe'                       => $metrics['peRatio'] ?? ($ratios['priceEarningsRatioTTM'] ?? null),
		'roe'                      => $metrics['roe'] ?? ($ratios['returnOnEquityTTM'] ?? null),
		'roa'                      => $metrics['roa'] ?? ($ratios['returnOnAssetsTTM'] ?? null),
		'roic'                     => $metrics['roic'] ?? ($ratios['returnOnCapitalEmployedTTM'] ?? null),
		'grossMargin'              => $ratios['grossProfitMarginTTM'] ?? null,
		'netMargin'                => $ratios['netProfitMarginTTM'] ?? null,
		'currentRatio'             => $metrics['currentRatio'] ?? null,
		'debtToEquity'             => $ratios['debtToEquityTTM'] ?? ($metrics['debtToEquity'] ?? null),
		'dividendYield'            => $ratios['dividendYieldTTM'] ?? ($metrics['dividendYield'] ?? null),
		'payoutRatio'              => $ratios['payoutRatioTTM'] ?? ($metrics['payoutRatio'] ?? null),
		'incomeQuality'            => $metrics['incomeQuality'] ?? null,
		'returnOnTangibleAssets'   => $metrics['returnOnTangibleAssets'] ?? null,
		'pegRatio'                 => $ratios['pegRatioTTM'] ?? null,
		'epsGrowth'                => $metrics['epsGrowth'] ?? ($growth['epsgrowth'] ?? null),
		'revenueGrowth'            => $growth['revenueGrowth'] ?? null,
		'bookValueperShareGrowth'  => $growth['bookValueperShareGrowth'] ?? null,
		'grahamNumber'             => $metrics['grahamNumber'] ?? null,
		'fcf'                      => $metrics['freeCashFlowPerShare'] ?? null,
		'eps'                      => $metrics['netIncomePerShare'] ?? null,
		'peRatio' 					=> $metrics['peRatio'] ?? ($ratios['priceEarningsRatioTTM'] ?? null),
	];

	return [
		'data'     => $data,
		'profile'  => $profile,
		'metrics'  => $metrics,
		'ratios'   => $ratios,
		'growth'   => $growth,
		'price'    => $price,
		'asofUsed' => $metrics['date'] ?? ($ratios['date'] ?? ($growth['date'] ?? null)),
	];
}

/** Fair Value via PE */
function fair_value_by_pe($eps, $target_pe) {
	return (is_numeric($eps) && is_numeric($target_pe)) ? ((float)$eps * (float)$target_pe) : null;
}

/** Gordon-ähnlicher FCF-Ansatz */
function fair_value_by_fcf($fcf, $g = 0.05, $d = 0.10) {
	if (!is_numeric($fcf) || $fcf <= 0) return null;
	$den = ($d - $g);
	if (!is_numeric($den) || $den <= 0) return null; // Schutz vor 0 oder negativ
	$v = ($fcf * (1 + $g)) / $den;
	return $v > 0 ? $v : null;
}

/**
 * Kernfunktion: Score aus bereits gemappten Daten berechnen.
 * $data_rating (optional) kann ['ratingScore','ratingLabel','analyst'=>['buy'=>..]] enthalten.
 */
function bewertung_fundamental_score_from_data(
	 array $data,
	 ?array $data_rating = null,
	 ?float $target_pe_override = null,
	 array $opts = []
 ): array {
	 $o = array_merge([
		 'enable_pe_fallback' => false,
		 'pe_fallback_bounds' => [8.0, 30.0],
	 ], $opts);
 
	 // Ziel-KGV bestimmen
	 $sector    = $data['sector'] ?? null;
	 $target_pe = $target_pe_override;
	 if ($target_pe === null && $sector && isset(SECTOR_DEFAULT_PE[$sector])) {
		 $target_pe = SECTOR_DEFAULT_PE[$sector];
	 }
	 if ($o['enable_pe_fallback'] && $target_pe === null && is_numeric($data['pe'] ?? null)) {
		 [$min,$max] = $o['pe_fallback_bounds'];
		 $pe = (float)$data['pe'];
		 $target_pe = max($min, min($max, $pe));
	 }
	 $target_pe_used = $target_pe;
 
	 $price        = $data['price'] ?? null;
	 $fairValuePE  = fair_value_by_pe($data['eps'] ?? null, $target_pe);
	 $fairValueFCF = fair_value_by_fcf($data['fcf'] ?? null);
 
	 $score   = 0;
	 $total   = 0;
	 $details = [];
 
	 // 25 Kriterien (dein bestehender Block)
	 add_point(c_between($data['pe'] ?? null, 0, 25), $score,$total,$details,'pe_0_25');
	 add_point(c_gt($data['roe'] ?? null, 0.15),      $score,$total,$details,'roe_gt_15');
	 add_point(c_gt($data['fcf'] ?? null, 0),         $score,$total,$details,'fcf_gt_0');
 
	 $cond = $data_rating['ratingScore'] ?? null;
	 add_point(is_numeric($cond) ? ($cond > 3.5) : null, $score,$total,$details,'ratingScore_gt_3_5');
 
	 $cond = $data_rating['analyst']['buy'] ?? null;
	 add_point(is_numeric($cond) ? ($cond > 30) : null, $score,$total,$details,'analyst_buy_gt_30');
 
	 add_point(c_price_below($price, $fairValuePE),                         $score,$total,$details,'price_below_fvPE');
	 add_point(c_price_below($price, $fairValueFCF),                        $score,$total,$details,'price_below_fvFCF');
	 add_point(c_between($data['pegRatio'] ?? null, 0, 1.5),                $score,$total,$details,'peg_between_0_1_5');
	 add_point(c_gt($data['dividendYield'] ?? null, 0.01),                  $score,$total,$details,'div_yield_gt_1pct');
	 add_point(c_lt($data['debtToEquity'] ?? null, 1),                      $score,$total,$details,'dte_lt_1');
	 add_point(c_gt($data['currentRatio'] ?? null, 1.2),                    $score,$total,$details,'current_ratio_gt_1_2');
	 add_point(c_price_below($price, $data['grahamNumber'] ?? null),        $score,$total,$details,'price_below_graham');
 
	 add_point(c_lt($data['payoutRatio'] ?? null, 0.6),                     $score,$total,$details,'payout_lt_60');
	 add_point(c_gt($data['incomeQuality'] ?? null, 1),                     $score,$total,$details,'income_quality_gt_1');
	 add_point(c_gt($data['roic'] ?? null, 0.2),                            $score,$total,$details,'roic_gt_20');
	 add_point(c_gt($data['returnOnTangibleAssets'] ?? null, 0.15),         $score,$total,$details,'rota_gt_15');
 
	 add_point(c_and(c_price_below($price, $fairValuePE  * 1.2), is_numeric($fairValuePE)),  $score,$total,$details,'price_below_fvPE_120');
	 add_point(c_and(c_price_below($price, $fairValueFCF * 1.2), is_numeric($fairValueFCF)), $score,$total,$details,'price_below_fvFCF_120');
 
	 add_point(c_gt($data['epsGrowth'] ?? null, 0.10),                      $score,$total,$details,'eps_growth_gt_10');
 
	 $label = $data_rating['ratingLabel'] ?? null;
	 add_point($label ? in_array($label, ['A','AA'], true) : null,          $score,$total,$details,'rating_label_A_or_AA');
 
	 $cond = $data_rating['analyst']['buy'] ?? null;
	 add_point(is_numeric($cond) ? ($cond >= 50) : null,                    $score,$total,$details,'analyst_buy_ge_50');
 
	 add_point(c_lt($data['pegRatio'] ?? null, 1),                          $score,$total,$details,'peg_lt_1');
	 add_point(c_gt($data['dividendYield'] ?? null, 0),                     $score,$total,$details,'div_yield_gt_0');
	 add_point(c_gt($data['revenueGrowth'] ?? null, 0.05),                  $score,$total,$details,'rev_growth_gt_5');
	 add_point(c_gt($data['bookValueperShareGrowth'] ?? null, 0.05),        $score,$total,$details,'bvps_growth_gt_5');
 
	 $name     = $data['name']     ?? ($o['name']     ?? ($data['symbol'] ?? ($o['symbol'] ?? null)));
	 $exchange = $data['exchange'] ?? ($o['exchange'] ?? null);
 
	 return [
		 'score'          => $score,
		 'total'          => $total,
		 'percent'        => $total ? round(100 * $score / $total, 1) : null,
		 'fairValues'     => ['pe' => $fairValuePE, 'fcf' => $fairValueFCF],
		 'target_pe_used' => $target_pe_used,
		 'details'        => $details,
		 'name'           => $name,
		 'exchange'       => $exchange,
	 ];
 }

function bewertung_fundamental_score(
	 string $symbol,
	 ?string $asof = null,
	 ?float $target_pe_override = null,
	 ?array $data_rating = null,
	 array $opts = []
 ): array {
	 $f = bewertung_fundamental_fetch_data($symbol, $asof);
 
	 $data      = $f['data']    ?? [];
	 $profile   = $f['profile'] ?? [];
	 $data['symbol']   = $symbol;
	 $data['name']     = $profile['companyName']       ?? $symbol;
	 $data['exchange'] = $profile['exchangeShortName'] ?? ($profile['exchange'] ?? null);
 
	 return bewertung_fundamental_score_from_data($data, $data_rating, $target_pe_override, $opts);
 }
