<?php
require_once __DIR__ . '/engine/engine.php';

if (isset($_GET['ajax']) && $_GET['ajax'] === '1') {
	header('Content-Type: application/json; charset=utf-8');

	$draw   = (int)($_GET['draw'] ?? 1);
	$start  = max(0, (int)($_GET['start'] ?? 0));
	$length = min(500, max(10, (int)($_GET['length'] ?? 50)));

	$search = trim((string)($_GET['search']['value'] ?? ''));

	$columns = [
		0 => 'ticker',
		1 => 'name',
		2 => 'exchange',
		3 => 'best_month',
		4 => 'best_winrate',
		5 => 'created_at',
		6 => 'created_at',
	];
	$orderColIdx = (int)($_GET['order'][0]['column'] ?? 6);
	$orderDir    = strtoupper($_GET['order'][0]['dir'] ?? 'DESC');
	$orderDir    = ($orderDir === 'ASC') ? 'ASC' : 'DESC';
	$orderCol    = $columns[$orderColIdx] ?? 'created_at';

	$where  = '';
	$params = [];
	if ($search !== '') {
		$where = "WHERE (ticker LIKE :q OR name LIKE :q OR exchange LIKE :q)";
		$params[':q'] = "%{$search}%";
	}

	$total = (int)$pdo->query("SELECT COUNT(*) FROM saisonale_aktien")->fetchColumn();

	$stmtCount = $pdo->prepare("SELECT COUNT(*) FROM saisonale_aktien {$where}");
	$stmtCount->execute($params);
	$filtered = (int)$stmtCount->fetchColumn();

	$sql = "
	  SELECT id, scan_id, ticker, name, exchange, best_month, best_winrate,
			 qualified_months, threshold_percent, min_years, direction, years_back,
			 data_json, created_at
	  FROM saisonale_aktien
	  {$where}
	  ORDER BY {$orderCol} {$orderDir}
	  LIMIT :start, :len
	";
	$stmt = $pdo->prepare($sql);
	foreach ($params as $k => $v) $stmt->bindValue($k, $v, PDO::PARAM_STR);
	$stmt->bindValue(':start', $start, PDO::PARAM_INT);
	$stmt->bindValue(':len',   $length, PDO::PARAM_INT);
	$stmt->execute();
	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

	$mon = [1=>'Jan',2=>'Feb',3=>'Mär',4=>'Apr',5=>'Mai',6=>'Jun',7=>'Jul',8=>'Aug',9=>'Sep',10=>'Okt',11=>'Nov',12=>'Dez'];

	$data = array_map(function($r) {
		return [
			'id'               => (int)$r['id'],
			'ticker'           => (string)$r['ticker'],
			'name'             => (string)$r['name'],
			'exchange'         => (string)($r['exchange'] ?? ''),
			'best_month'       => (int)($r['best_month'] ?? 0),
			'best_winrate'     => (int)($r['best_winrate'] ?? 0),
			'qualified_months' => (string)($r['qualified_months'] ?? ''),
			'data_json'        => (string)($r['data_json'] ?? ''),
			'created_at'       => (string)$r['created_at'],
		];
	}, $rows);

	echo json_encode([
		'draw'            => $draw,
		'recordsTotal'    => $total,
		'recordsFiltered' => $filtered,
		'data'            => $data,
	], JSON_UNESCAPED_UNICODE);
	exit;
}

$requires_search = true;
$requires_chartjs = true;
$requires_dataTables = true;
require_once __DIR__ . '/views/header.php';
require_once __DIR__ . '/views/navigation.php';
?>
<main class="flex-grow-1">
	<div class="container my-5">
		<h3 class="mb-0">Saisonale Aktien</h3>
		<small class="text-muted">Treffer der Methode: Saisonalität 100</small>
		
		<!-- Charts Grid -->
		<div class="row g-3 my-4" id="seasonalCharts">
			<div class="col-lg-6">
				<div class="card h-100">
					<div class="card-body">
						<div class="d-flex justify-content-between align-items-center mb-2">
							<h6 class="mb-0">Monat × Börse (Stacked)</h6>
						</div>
						<div style="height:200px;">
							<canvas id="chartMonthExchange" height="180"></canvas>
						</div>
					</div>
				</div>
			</div>
			<div class="col-lg-6">
				<div class="card h-100">
					<div class="card-body">
						<div class="d-flex justify-content-between align-items-center mb-2">
							<h6 class="mb-0">Histogramm: qualifizierte Monate</h6>
						</div>
						<div style="height:200px;">
							<canvas id="chartHistogram" height="180"></canvas>
						</div>
					</div>
				</div>
			</div>
			<div class="col-lg-6">
				<div class="card h-100">
					<div class="card-body">
						<div class="d-flex justify-content-between align-items-center mb-2">
							<h6 class="mb-0">Stabilität vs. Winrate</h6>
						</div>
						<div style="height:200px;">
							<canvas id="chartScatter" height="180"></canvas>
						</div>
					</div>
				</div>
			</div>
			<div class="col-lg-6">
				<div class="card h-100">
					<div class="card-body">
						<div class="d-flex justify-content-between align-items-center mb-2">
							<h6 class="mb-0">Winrate‑Verteilung je Monat (Boxplot)</h6>
						</div>
						<div style="height:200px;">
							<canvas id="chartBoxplot" height="180"></canvas>
						</div>
					</div>
				</div>
			</div>
		</div>
		
		<div class="d-flex justify-content-between mt-4">
			<h5>Scan-Ergebnisse <small id="resultCount" class="text-muted"></small></h5>
			<div class="d-flex align-items-center mb-3 gap-2 flex-wrap">
				<div class="dropdown">
					<button class="btn btn-outline-success btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
					Exportieren
					</button>
					<ul class="dropdown-menu" id="exportMenu">
						<li><a class="dropdown-item export-link" data-format="json" href="#">Als JSON</a></li>
						<li><a class="dropdown-item export-link" data-format="csv" href="#">Als CSV</a></li>
						<li><a class="dropdown-item export-link" data-format="pdf" href="#">Als PDF</a></li>
					</ul>
				</div>
				<button class="btn btn-sm btn-outline-danger" id="deleteAllBtn">
					Alle löschen
				</button>
			</div>
		</div>
		<div class="table-responsive mt-2">
			<table class="table table-striped table-bordered" id="saisonaleTable">
				<thead class="table-dark">
					<tr>
						<th class="fw-bold">Symbol</th>
						<th>Unternehmensname</th>
						<th>Börse</th>
						<th>Saisonaler Monat</th>
						<th>Quote (%)</th>
						<th>Weitere Monate</th>
						<th>Datum Scan</th>
						<th></th>
					</tr>
				</thead>
				<tbody></tbody>
			</table>
		</div>
	</div>
</main>
<?php require_once __DIR__ . '/views/footer.php'; ?>

<script>
document.addEventListener('DOMContentLoaded', function () {

  // Monatsnamen
  const monthName = m => {
	const N = ['', 'Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'];
	return (m >=1 && m <= 12) ? N[m] : '–';
  };

  // DataTable initialisieren
  const dt = $('#saisonaleTable').DataTable({
	serverSide: true,
	processing: true,
	ajax: {
	  url: 'saisonale-aktien.php',
	  type: 'GET',
	  data: function (d) { d.ajax = '1'; }
	},
	language: { url: 'assets/js/data-tables_de-DE.json' }, // falls vorhanden
	columns: [
	  { data: 'ticker', title: 'Ticker' },
	  { data: 'name', title: 'Name' },
	  { data: 'exchange', title: 'Börse' },

	  // Saisonaler Monat (nur Name)
	  {
		data: 'best_month',
		title: 'Saisonaler Monat',
		render: (d) => monthName(parseInt(d, 10))
	  },

	  // Quote (%): reine Zahl (sortier-/filterbar)
	  {
		data: 'best_winrate',
		title: 'Quote (%)',
		className: 'text-end',
		render: (d, type) => {
		  const v = parseInt(d, 10);
		  if (type === 'sort' || type === 'type' || type === 'filter') return isNaN(v) ? 0 : v;
		  return isNaN(v) ? '–' : v.toString();
		}
	  },

	  // Weitere Monate (aus qualified_months + data_json.winrates_percent)
	  {
		data: null,
		title: 'Weitere Monate',
		orderable: false,
		render: (row) => {
		  const best = parseInt(row.best_month, 10);
		  const qual = (row.qualified_months || '').split(',')
						.map(s => parseInt(s.trim(), 10))
						.filter(n => Number.isInteger(n) && n >= 1 && n <= 12 && n !== best);

		  if (!qual.length) return '–';

		  let wins = {};
		  try {
			const dj = row.data_json ? JSON.parse(row.data_json) : null;
			wins = (dj && dj.winrates_percent) ? dj.winrates_percent : {};
		  } catch (_) {}

		  return qual.map(m => {
			const w = parseInt((wins && wins[m] != null) ? wins[m] : row.best_winrate, 10);
			return `${monthName(m)} (${isNaN(w) ? '–' : w}%)`;
		  }).join(', ');
		}
	  },

	  { data: 'created_at', title: 'Datum' },

	  // Letzte Spalte: Eintrag löschen
	  {
		data: 'id',
		title: '',
		orderable: false,
		searchable: false,
		className: 'text-end',
		render: function (id, type, row) {
		  if (type === 'display') {
			return `<button class="btn btn-link text-danger p-0" onclick="deleteSeasonalRow(${id})" title="Eintrag löschen"><small>löschen</small></button>`;
		  }
		  return id;
		}
	  }
	],
	// wichtig: created_at steht bei Index 6 (0-basiert), also hier nicht ändern
	order: [[6, 'desc']],
	pageLength: 50,
	lengthMenu: [[25, 50, 100, -1], [25, 50, 100, "Alle"]],
	stripeClasses: ['table-light', 'table-white']
  });
  
  // Headline-Zähler aktualisieren
  dt.on('xhr.dt', function (e, settings, json) {
	if (!json) return;
	const total = json.recordsTotal ?? 0;
	const filtered = json.recordsFiltered ?? total;
	const el = document.getElementById('resultCount');
	if (el) {
	  const same = Number(filtered) === Number(total);
	  el.textContent = same
		? ` (${total.toLocaleString()} gesamt)`
		: ` (${filtered.toLocaleString()} angezeigt · ${total.toLocaleString()} gesamt)`;
	}
  });

  // ---- Export-Handler (JSON/CSV/PDF) ----
  // Erwartet die Endpoints aus meiner Vorlage:
  //   execute/aktien-scanner/export_seasonal.php?format=json|csv|pdf
  document.querySelectorAll('.export-link').forEach(el => {
	el.addEventListener('click', function (e) {
	  e.preventDefault();
	  const format = this.getAttribute('data-format') || 'json';
	  const url = `execute/aktien-scanner/saisonale-aktien_export.php?format=${encodeURIComponent(format)}`;
	  const a = document.createElement('a');
	  a.href = url;
	  a.setAttribute('download', '');
	  document.body.appendChild(a);
	  a.click();
	  a.remove();
	});
  });

  // ---- Alle löschen ----
  // Erwartet den Endpoint:
  //   POST execute/aktien-scanner/seasonal_delete_all.php
  const deleteAllBtn = document.getElementById('deleteAllBtn');
  if (deleteAllBtn) {
	deleteAllBtn.addEventListener('click', async function () {
	  if (!confirm('Wirklich ALLE saisonalen Einträge löschen?')) return;
	  const original = deleteAllBtn.innerHTML;
	  deleteAllBtn.disabled = true;
	  deleteAllBtn.innerHTML = 'Lösche…';
	  try {
		const res = await fetch('execute/saisonale-aktien/saisonale-aktien_delete_all.php', {
		  method: 'POST',
		  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
		  // Falls du später nach scan_id o.ä. filtern willst: body: new URLSearchParams({ scan_id: window.currentScanId || '' }).toString()
		  body: ''
		});
		const json = await res.json();
		if (!json.success) throw new Error(json.message || 'Unbekannter Fehler');
		dt.ajax.reload(null, false);
		alert(`Gelöscht: ${json.deleted_rows} Einträge`);
	  } catch (err) {
		console.error(err);
		alert('Fehler beim Löschen: ' + err.message);
	  } finally {
		deleteAllBtn.disabled = false;
		deleteAllBtn.innerHTML = original;
	  }
	});
  }

  // ---- Einzelzeile löschen (global, damit onclick funktioniert) ----
  window.deleteSeasonalRow = async function (id) {
	if (!confirm('Diesen Eintrag löschen?')) return;
	try {
	  const res = await fetch('execute/saisonale-aktien/saisonale-aktien_delete_scan_result.php', {
		method: 'POST',
		headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
		body: new URLSearchParams({ id: String(id) }).toString()
	  });
	  const json = await res.json();
	  if (!json.success) throw new Error(json.message || 'Unbekannter Fehler');
	  dt.ajax.reload(null, false);
	} catch (err) {
	  console.error(err);
	  alert('Fehler beim Löschen: ' + err.message);
	}
  };

});
</script>

<script>
(function () {
  const STATS_URL = 'execute/saisonale-aktien/saisonale-aktien_stats.php';
  const MONTHS = ['', 'Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'];

  let chMonthExchange, chHistogram, chScatter, chBoxplot;

  async function fetchJSON(url, opt) {
	const res = await fetch(url, opt);
	const txt = await res.text();
	if (!res.ok) throw new Error('HTTP ' + res.status + ' ' + res.statusText + ': ' + txt.slice(0, 200));
	try { return JSON.parse(txt); } catch (e) { console.error('Invalid JSON from', url, txt); throw e; }
  }

  async function fetchStats() {
	try {
	  const q = (typeof dt !== 'undefined') ? dt.search() : '';
	  const url = STATS_URL + '?' + new URLSearchParams({ search: q, top_n: 5 }).toString();
	  const json = await fetchJSON(url);
	  if (!json || json.success === false) throw new Error((json && json.message) ? json.message : 'Fehler beim Laden der Stats');
	  return json;
	} catch (e) {
	  console.error(e);
	  return null;
	}
  }

  function buildStackedMonthExchange(json) {
	const labels = MONTHS.slice(1);
	const top = json.topExchanges || [];
	const othersKey = json.othersKey || 'Sonstige';

	// Map: month -> exchange -> count
	const map = {};
	(json.byMonthExchange || []).forEach(function (r) {
	  const m = r.month, ex = r.exchange, c = r.count || 0;
	  if (!map[m]) map[m] = {};
	  map[m][ex] = c;
	});

	const seriesKeys = top.concat([othersKey]);
	const datasets = seriesKeys.map(function (exKey) {
	  return {
		label: exKey,
		data: labels.map(function (_, idx) {
		  const m = idx + 1;
		  const row = map[m] || {};
		  return row[exKey] || 0;
		}),
		borderWidth: 1
	  };
	});

	const data = { labels: labels, datasets: datasets };
	const options = {
		responsive: true,
		maintainAspectRatio: false,
		animation: false,
		datasets: { bar: { maxBarThickness: 24 } },
		plugins: { legend: { position: 'top' }, tooltip: { mode: 'index', intersect: false } },
		scales: { x: { stacked: true }, y: { stacked: true, beginAtZero: true, ticks: { precision: 0 } } }
	  };
	
	  const ctx = document.getElementById('chartMonthExchange');
	  const prev = Chart.getChart(ctx); if (prev) prev.destroy();
	  chMonthExchange = new Chart(ctx, { type: 'bar', data: data, options: options });
  }

  function buildHistogram(json) {
	const binsOrder = ['1','2','3-4','5-6','7-9','10-12'];
	const map = {};
	(json.histQualifiedMonths || []).forEach(function (b) { map[b.bin] = b.count || 0; });

	const data = {
	  labels: binsOrder,
	  datasets: [{ label: 'Assets', data: binsOrder.map(function (k) { return map[k] || 0; }), borderWidth: 1 }]
	};
	const options = {
		responsive: true,
		maintainAspectRatio: false,
		animation: false,
		datasets: { bar: { maxBarThickness: 24 } },
		plugins: { legend: { display: false } },
		scales: { y: { beginAtZero: true, ticks: { precision: 0 } } }
	  };
	
	  const ctx = document.getElementById('chartHistogram');
	  const prev = Chart.getChart(ctx); if (prev) prev.destroy();
	  chHistogram = new Chart(ctx, { type: 'bar', data: data, options: options });
  }

  function buildScatter(json) {
	const points = (json.scatter || []).map(function (r) {
	  return {
		x: r.min_years || 0,
		y: r.best_winrate || 0,
		label: r.ticker + ' (' + r.exchange + ')',
		r: Math.max(3, Math.min(9, (r.threshold_percent || 0) / 10 + 3))
	  };
	});

	const data = {
		datasets: [{
		  label: 'Assets',
		  data: points,
		  parsing: false,
		  pointRadius: function (ctx) { return (ctx.raw && ctx.raw.r) ? ctx.raw.r : 4; }
		}]
	  };
	  const options = {
		responsive: true,
		maintainAspectRatio: false,
		animation: false,
		plugins: {
		  legend: { display: false },
		  tooltip: { callbacks: { label: function (ctx) {
			const p = ctx.raw; return p.label + ' • Jahre ' + p.x + ' • ' + p.y + '%';
		  }}}
		},
		scales: {
		  x: { title: { display: true, text: 'min_years' }, beginAtZero: true },
		  y: { title: { display: true, text: 'best_winrate (%)' }, min: 0, max: 100 }
		}
	  };

	const ctx = document.getElementById('chartScatter');
	  const prev = Chart.getChart(ctx); if (prev) prev.destroy();
	  chScatter = new Chart(ctx, { type: 'scatter', data: data, options: options });
  }

  function buildBoxplot(json) {
	if (typeof ChartBoxPlot === 'undefined') {
	  console.warn('ChartBoxPlot nicht geladen.');
	  return;
	}
	const labels = MONTHS.slice(1);
	const arrs = [];
	for (var m = 1; m <= 12; m++) {
	  var arr = (json.winratesByMonth && json.winratesByMonth[m]) ? json.winratesByMonth[m] : [];
	  arrs.push(arr);
	}

	const data = {
	  labels: labels,
	  datasets: [{ label: 'Winrate %', type: 'boxplot', data: arrs }]
	};
	const options = {
		responsive: true,
		maintainAspectRatio: false,
		animation: false,
		plugins: { legend: { display: false } },
		scales: { y: { min: 0, max: 100, title: { display: true, text: 'Winrate (%)' } } }
	  };
	
	  const ctx = document.getElementById('chartBoxplot');
	  const prev = Chart.getChart(ctx); if (prev) prev.destroy();
	  chBoxplot = new Chart(ctx, { type: 'boxplot', data: data, options: options });
  }

  async function refreshCharts() {
	const json = await fetchStats();
	if (!json) return;
	buildStackedMonthExchange(json);
	buildHistogram(json);
	buildScatter(json);
	buildBoxplot(json);
  }

  if (typeof dt !== 'undefined') {
	dt.on('xhr.dt', refreshCharts);
	dt.on('search.dt', refreshCharts);
  }
  refreshCharts();

})();
</script>

<?php require_once __DIR__ . '/views/footer.php'; ?>
