<?php
declare(strict_types=1);

require_once __DIR__ . '/include/image_fetch.php';

use WList\Net\ImageFetch;

/* ========= Session & Bootstrap ========= */
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
session_set_cookie_params([
  'lifetime' => 0,
  'path' => '/',
  'secure' => $secure,
  'httponly' => true,
  'samesite' => 'Lax',
]);
session_name('WLISTSESSID');
session_start();
umask(0022); // sorgt für 0644/0755 als Default für neu erstellte Dateien/Ordner

require_once __DIR__ . '/config/config.php';

// ===== Debug Toggle =====
if (!empty($app_debug)) {
  ini_set('display_errors', '1');
  ini_set('display_startup_errors', '1');
  ini_set('log_errors', '1');
  if (!is_dir(__DIR__ . '/logs')) {
    @mkdir(__DIR__ . '/logs', 0750, true);
  }
  ini_set('error_log', __DIR__ . '/logs/php-error.log');
  error_reporting(E_ALL);
} else {
  ini_set('display_errors', '0');
  ini_set('display_startup_errors', '0');
  ini_set('log_errors', '1');
  if (!is_dir(__DIR__ . '/logs')) {
    @mkdir(__DIR__ . '/logs', 0750, true);
  }
  ini_set('error_log', __DIR__ . '/logs/php-error.log');
  error_reporting(E_ALL);
}

/* ============= Helpers ============= */
function fail(string $msg = 'Unerwarteter Fehler', int $code = 400): void
{
  http_response_code($code);
  exit($msg);
}
function require_csrf(): void
{
  $t = (string) ($_POST['csrf'] ?? '');
  if (empty($_SESSION['csrf']) || !hash_equals($_SESSION['csrf'], $t))
    fail('Ungültiges CSRF-Token', 403);
}
function require_logged_in(): int
{
  if (!isset($_SESSION['listid']))
    fail('Nicht eingeloggt', 403);
  return (int) $_SESSION['listid'];
}
function db(): mysqli
{
  global $servername, $username, $password, $db;
  $conn = new mysqli($servername, $username, $password, $db);
  if ($conn->connect_error)
    fail('Interner Fehler (DB)', 500);
  $conn->set_charset('utf8mb4');
  return $conn;
}
function parse_price_to_cents(string $in): int
{
  $clean = preg_replace('/[^\d,\.]/', '', $in ?? '');
  $norm = str_replace('.', '', $clean);
  $norm = str_replace(',', '.', $norm);
  if ($norm === '' || !is_numeric($norm))
    return 0;
  $cents = (int) round((float) $norm * 100);
  if ($cents < 0)
    $cents = 0;
  if ($cents > 100000000)
    $cents = 100000000; // 1 Mio €
  return $cents;
}
function is_valid_http_url(string $url): bool
{
  if (!filter_var($url, FILTER_VALIDATE_URL))
    return false;
  $p = parse_url($url);
  if (!$p || empty($p['scheme']) || empty($p['host']))
    return false;
  $s = strtolower($p['scheme']);
  return $s === 'http' || $s === 'https';
}

/* ============= Controller ============= */

require_csrf();
$sessionListId = require_logged_in();

$action = strtolower(trim((string) ($_POST['action'] ?? '')));
$ItemTitle = trim((string) ($_POST['ItemTitle'] ?? ''));
$ItemDescription = trim((string) ($_POST['ItemDescription'] ?? ''));
$ItemPrice = parse_price_to_cents((string) ($_POST['ItemPrice'] ?? ''));
$ItemQty = isset($_POST['ItemQty']) ? max(1, (int) $_POST['ItemQty']) : 1;
$ItemLink = trim((string) ($_POST['ItemLink'] ?? ''));
$ItemImageUrl = trim((string) ($_POST['ItemImage'] ?? ''));   // optional URL zum Pull
$ListUUID = trim((string) ($_POST['ItemListUUID'] ?? ''));
$sortbyTransfer = (string) ($_POST['sortby_transfer'] ?? 'priority');

$removeImage = isset($_POST['RemoveImage']) && ($_POST['RemoveImage'] === '1');
$WhishID = isset($_POST['WhishID']) ? (int) $_POST['WhishID'] : 0; // bei edit

if (!preg_match('/^[0-9a-fA-F-]{32,36}$/', $ListUUID))
  fail('Liste nicht autorisiert', 403);

$conn = db();

/* UUID -> int ID */
$stmt = $conn->prepare('SELECT ID FROM lists WHERE uuid = ?');
$stmt->bind_param('s', $ListUUID);
$stmt->execute();
$res = $stmt->get_result();
if (!$res || !($row = $res->fetch_assoc())) {
  $stmt->close();
  $conn->close();
  fail('Liste nicht autorisiert', 403);
}
$ListID = (int) $row['ID'];
$stmt->close();

/* Session muss zu dieser Liste gehören */
if ($ListID !== $sessionListId) {
  $conn->close();
  fail('Liste nicht autorisiert', 403);
}

/* Validierungen (add & edit) */
if ($ItemTitle === '')
  fail('Titel fehlt', 400);
if ($ItemLink !== '' && !is_valid_http_url($ItemLink))
  fail('Ungültiger Angebotslink', 400);

/* Optional: Bild von externer URL holen */
$imageLocalLink = null;
if (!$removeImage && $ItemImageUrl !== '') {

  $whitelist = $image_host_whitelist ?? null;

  $fetch = ImageFetch::download($ItemImageUrl, [
    'max_bytes' => 8_000_000,
    'timeout' => 12,
    'connect_timeout' => 5,
    'retries' => 4,
    'retry_backoff_ms' => 300,
    'whitelist_hosts' => $whitelist,
    'ip_resolve_v4' => true,
    'referer' => 'auto',
    'log_prefix' => 'wishlist-img',
  ]);

  if (!$fetch['ok']) {
    error_log("wishlist image error: http=" . ($fetch['http_code'] ?? 0) . " curl=" . ($fetch['curl_err'] ?? '-') . " url=$ItemImageUrl");
    $conn->close();
    fail('Bild-Download fehlgeschlagen', 400);
  }

  $info = @getimagesize($fetch['tmp_path']);
  $mime = $info['mime'] ?? $fetch['mime'] ?? 'image/*';
  if (stripos($mime, 'image/') !== 0) {
    @unlink($fetch['tmp_path']);
    $conn->close();
    fail('Link ist kein gültiges Bild', 400);
  }

  global $imagedir;
  if (!is_dir($imagedir))
    @mkdir($imagedir, 0755, true);
  $filename = ImageFetch::safeFileNameFromUrl($ItemImageUrl);
  $target = rtrim($imagedir, '/') . '/' . $filename;

  if (!@rename($fetch['tmp_path'], $target)) {
    if (!@copy($fetch['tmp_path'], $target)) {
      @unlink($fetch['tmp_path']);
      $conn->close();
      fail('Bildspeicherung fehlgeschlagen', 500);
    }
    @unlink($fetch['tmp_path']);
  }
  @chmod($target, 0644);
  $imageLocalLink = $filename;
}

/* ====== ADD ====== */
if ($action === 'add') {
  // nächste Priority ermitteln
  $next = 1;
  $s = $conn->prepare('SELECT COALESCE(MAX(priority),0) AS maxp FROM wishes WHERE wishlist = ?');
  $s->bind_param('i', $ListID);
  $s->execute();
  $r = $s->get_result();
  if ($r && $m = $r->fetch_assoc())
    $next = ((int) $m['maxp']) + 1;
  $s->close();

  $stmt = $conn->prepare('
  INSERT INTO wishes (title, description, link, image, price, wishlist, priority, qty)
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
');
  $link = $ItemLink !== '' ? $ItemLink : null;
  $image = $imageLocalLink !== null ? $imageLocalLink : null;
  $stmt->bind_param(
    'ssssiiii',
    $ItemTitle,
    $ItemDescription,
    $link,
    $image,
    $ItemPrice,
    $ListID,
    $next,
    $ItemQty
  );

  if (!$stmt->execute()) {
    $stmt->close();
    $conn->close();
    fail('Speichern fehlgeschlagen', 500);
  }
  $stmt->close();
}
/* ====== EDIT ====== */ elseif ($action === 'edit') {
  if ($WhishID <= 0) {
    $conn->close();
    fail('Ungültige Item-ID', 400);
  }

  // Besitz prüfen & altes Bild holen
  $stmt = $conn->prepare('SELECT image FROM wishes WHERE ID = ? AND wishlist = ?');
  $stmt->bind_param('ii', $WhishID, $ListID);
  $stmt->execute();
  $res = $stmt->get_result();
  if (!$res || !($row = $res->fetch_assoc())) {
    $stmt->close();
    $conn->close();
    fail('Item nicht gefunden/autorisiert', 404);
  }
  $oldImage = (string) $row['image'];
  $stmt->close();

  // Bild-Entscheidung: entfernen, ersetzen oder behalten
  $newImage = $oldImage;
  if ($removeImage) {
    if (!empty($oldImage)) {
      global $imagedir;
      $full = rtrim($imagedir, '/') . '/' . $oldImage;
      if (is_file($full))
        @unlink($full);
    }
    $newImage = '';
  } elseif ($imageLocalLink !== null) {
    if (!empty($oldImage)) {
      global $imagedir;
      $full = rtrim($imagedir, '/') . '/' . $oldImage;
      if (is_file($full))
        @unlink($full);
    }
    $newImage = $imageLocalLink;
  }

  $link = $ItemLink !== '' ? $ItemLink : null;
  $imgNullable = ($newImage !== '') ? $newImage : null;

  $stmt = $conn->prepare(
    'UPDATE wishes SET title=?, description=?, link=?, image=?, price=?, qty=? WHERE ID=? AND wishlist=?'
  );
  $stmt->bind_param(
    'sssssiii',
    $ItemTitle,
    $ItemDescription,
    $link,
    $imgNullable,
    $ItemPrice,
    $ItemQty,
    $WhishID,
    $ListID
  );

  if (!$stmt->execute()) {
    $stmt->close();
    $conn->close();
    fail('Update fehlgeschlagen', 500);
  }
  $stmt->close();
}
/* ====== Unbekannt ====== */ else {
  $conn->close();
  fail('Unbekannte Aktion', 400);
}

$conn->close();

/* Redirect zurück (sicher, mit UUID) */
$redirect = (string) ($_SERVER['HTTP_REFERER'] ?? '');
if ($redirect === '' || stripos($redirect, 'http') !== 0) {
  $host = $_SERVER['HTTP_HOST'] ?? '';
  $scheme = $secure ? 'https' : 'http';
  $qs = '?list=' . urlencode($ListUUID);
  if ($sortbyTransfer !== '')
    $qs .= '&sort=' . urlencode($sortbyTransfer);
  $redirect = $scheme . '://' . $host . '/' . $qs;
}
header('Location: ' . $redirect, true, 303);
exit;
