<?php
declare(strict_types=1);

/* doc-project | caisse-aqp/public/api/_lib/onlinePayments.php | Fournit l’accès centralisé aux paiements en ligne validés, leurs libellés et leurs montants agrégés par commande/point de vente afin d’alimenter la validation de règlement et le rattrapage d’impression automatique des tickets clients. | Expose: onlinePaymentsOrderInfoForStore, format_vads_trans_date, get_successful_online_payments_by_order_id, get_successful_online_payment_totals_by_order_id, has_successful_online_payment_for_order | Dépend de: PDO, config.php, pos_pay | Impacte: lecture des paiements, affichage des encaissements, logique de validation de règlement, détection des commandes intégralement payées | Tables: pos_pay(vads_order_id, vads_amount, vads_trans_date, vads_trans_id, vads_result, vads_order_info) */
/**
 * public/api/_lib/onlinePayments.php
 *
 * Récupération des paiements en ligne (pos_pay) groupée.
 * - Filtre "succès" : vads_result = '00'
 * - Filtre projet/PDV : vads_order_info = $orderInfo (dépend du store lan|pel : LANCON / PELISSANNE en bdd)
 */

/**
 * Mapping store -> vads_order_info.
 * Recommandé: définir ONLINE_PAYMENTS_ORDER_INFO_MAP dans config.php, ex:
 *   define('ONLINE_PAYMENTS_ORDER_INFO_MAP', ['lan' => 'LANCON', 'pel' => 'PELISSANNE']);
 *
 * Fallbacks supportés (si besoin) :
 * - define('LAN_ORDER_INFO', '...'), define('PEL_ORDER_INFO', '...')
 * - define('ORDER_INFO_LAN', '...'), define('ORDER_INFO_PEL', '...')
 */
function onlinePaymentsOrderInfoForStore(string $store): ?string {
  $s = strtolower(trim($store));
  if ($s !== 'lan' && $s !== 'pel') return null;

  if (defined('ONLINE_PAYMENTS_ORDER_INFO_MAP')) {
    $m = constant('ONLINE_PAYMENTS_ORDER_INFO_MAP');
    if (is_array($m) && isset($m[$s]) && is_string($m[$s]) && $m[$s] !== '') {
      return (string)$m[$s];
    }
  }

  if ($s === 'lan') {
    if (defined('LAN_ORDER_INFO') && is_string(constant('LAN_ORDER_INFO')) && constant('LAN_ORDER_INFO') !== '') return (string)constant('LAN_ORDER_INFO');
    if (defined('ORDER_INFO_LAN') && is_string(constant('ORDER_INFO_LAN')) && constant('ORDER_INFO_LAN') !== '') return (string)constant('ORDER_INFO_LAN');
  }
  if ($s === 'pel') {
    if (defined('PEL_ORDER_INFO') && is_string(constant('PEL_ORDER_INFO')) && constant('PEL_ORDER_INFO') !== '') return (string)constant('PEL_ORDER_INFO');
    if (defined('ORDER_INFO_PEL') && is_string(constant('ORDER_INFO_PEL')) && constant('ORDER_INFO_PEL') !== '') return (string)constant('ORDER_INFO_PEL');
  }

  // Defaults DB (strict business rule): LANCON / PELISSANNE
  if ($s === 'lan') return 'LANCON';
  if ($s === 'pel') return 'PELISSANNE';
  return null;
}

/**
 * Tente de formater vads_trans_date (souvent au format YYYYMMDDHHMMSS).
 * Retourne une chaîne lisible, sinon la valeur brute.
 */
function format_vads_trans_date($raw): ?string {
  if ($raw === null) return null;
  $s = (string)$raw;

  if (preg_match('/^\d{14}$/', $s)) {
    $dt = DateTime::createFromFormat('YmdHis', $s, new DateTimeZone('Europe/Paris'));
    if ($dt instanceof DateTime) return $dt->format('d/m/Y H:i:s');
  }
  if (preg_match('/^\d{8}$/', $s)) {
    $dt = DateTime::createFromFormat('Ymd', $s, new DateTimeZone('Europe/Paris'));
    if ($dt instanceof DateTime) return $dt->format('d/m/Y');
  }
  return $s;
}

/**
 * Retourne un tableau indexé par orderId :
 * [
 *   123 => [
 *     ['amount_eur' => 12.50, 'label' => '06/02/2026 12:34:56 • TX 000123'],
 *     ...
 *   ],
 * ]
 *
 * Filtre :
 * - Toujours: vads_result = '00'
 * - Toujours: vads_order_info = $orderInfo (anti-collision entre points de vente)
 *
 * $orderInfo peut être :
 * - soit directement la valeur attendue en bdd (LANCON / PELISSANNE),
 * - soit le code store ('lan' / 'pel') auquel cas on mappe automatiquement.
 * Si on ne parvient pas à déterminer vads_order_info, on retourne [] (strict).
 */
function get_successful_online_payments_by_order_id(PDO $pdo, array $orderIds, $orderInfo): array {
  $orderIds = array_values(array_unique(array_map('intval', $orderIds)));
  if (empty($orderIds)) return [];

  $oi = is_string($orderInfo) ? trim($orderInfo) : '';
  // Accept store code ('lan'|'pel') as input and map it to vads_order_info.
  $storeCandidate = strtolower($oi);
  if ($storeCandidate === 'lan' || $storeCandidate === 'pel') {
    $mapped = onlinePaymentsOrderInfoForStore($storeCandidate);
    $oi = is_string($mapped) ? trim($mapped) : '';
  }
  if ($oi === '') return []; // strict anti-collision: do not query without vads_order_info.

  $placeholders = implode(',', array_fill(0, count($orderIds), '?'));
  $sql = "
    SELECT
      vads_order_id,
      vads_amount,
      vads_trans_date,
      vads_trans_id
    FROM pos_pay
    WHERE vads_order_id IN ($placeholders)
      AND vads_result = '00'
      AND vads_order_info = ?
  ";
  $sql .= " ORDER BY vads_order_id ASC, vads_trans_date ASC, vads_trans_id ASC ";

  $stmt = $pdo->prepare($sql);
  $params = $orderIds;
  $params[] = $oi;
  $stmt->execute($params);

  $byOrder = [];
  while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $oid = isset($row['vads_order_id']) ? (int)$row['vads_order_id'] : 0;
    if ($oid <= 0) continue;

    $amountCent = isset($row['vads_amount']) ? (int)$row['vads_amount'] : 0;
    $amountEur = $amountCent / 100;

    $dateLabel = format_vads_trans_date($row['vads_trans_date'] ?? null);
    $tx = isset($row['vads_trans_id']) && $row['vads_trans_id'] !== '' ? (string)$row['vads_trans_id'] : null;

    $labelParts = [];
    if (!empty($dateLabel)) $labelParts[] = $dateLabel;
    if (!empty($tx)) $labelParts[] = 'TX ' . $tx;
    $label = !empty($labelParts) ? implode(' • ', $labelParts) : 'Paiement';

    if (!isset($byOrder[$oid])) $byOrder[$oid] = [];
    $byOrder[$oid][] = [
      'amount_eur' => $amountEur,
      'label' => $label,
    ];
  }

  return $byOrder;
}

/**
 * Retourne un tableau indexé par orderId avec le total des paiements réussis en centimes :
 * [
 *   123 => 2500,
 *   124 => 1200,
 * ]
 *
 * Même règle stricte que get_successful_online_payments_by_order_id():
 * - vads_result = '00'
 * - vads_order_info = mapping strict du store / orderInfo
 */
function get_successful_online_payment_totals_by_order_id(PDO $pdo, array $orderIds, $orderInfo): array {
  $orderIds = array_values(array_unique(array_map('intval', $orderIds)));
  if (empty($orderIds)) return [];

  $oi = is_string($orderInfo) ? trim($orderInfo) : '';
  $storeCandidate = strtolower($oi);
  if ($storeCandidate === 'lan' || $storeCandidate === 'pel') {
    $mapped = onlinePaymentsOrderInfoForStore($storeCandidate);
    $oi = is_string($mapped) ? trim($mapped) : '';
  }
  if ($oi === '') return [];

  $placeholders = implode(',', array_fill(0, count($orderIds), '?'));
  $sql = "
    SELECT
      vads_order_id,
      COALESCE(SUM(vads_amount), 0) AS total_amount_cent
    FROM pos_pay
    WHERE vads_order_id IN ($placeholders)
      AND vads_result = '00'
      AND vads_order_info = ?
    GROUP BY vads_order_id
  ";

  $stmt = $pdo->prepare($sql);
  $params = $orderIds;
  $params[] = $oi;
  $stmt->execute($params);

  $totals = [];
  while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $oid = isset($row['vads_order_id']) ? (int)$row['vads_order_id'] : 0;
    if ($oid <= 0) continue;
    $totals[$oid] = isset($row['total_amount_cent']) ? (int)$row['total_amount_cent'] : 0;
  }

  return $totals;
}

/**
 * has_successful_online_payment_for_order(PDO $pdo, string $store, int $orderId) -> bool
 * - Strict business rule for "deposit paid?":
 *   - pos_pay.vads_result = '00'
 *   - pos_pay.vads_order_id = orderId
 *   - pos_pay.vads_order_info = store-mapped value (LANCON / PELISSANNE)
 *
 * Note:
 * - If mapping is missing, we RETURN false (treat as unpaid) and caller should log.
 */
function has_successful_online_payment_for_order(PDO $pdo, string $store, int $orderId): bool {
  $oid = (int)$orderId;
  if ($oid <= 0) return false;

  $orderInfo = onlinePaymentsOrderInfoForStore($store);
  $oi = is_string($orderInfo) ? trim($orderInfo) : '';
  if ($oi === '') {
    // Strict: mapping missing => cannot assert payment belongs to this store.
    return false;
  }

  $stmt = $pdo->prepare("
    SELECT 1
    FROM pos_pay
    WHERE vads_order_id = :oid
      AND vads_result = '00'
      AND vads_order_info = :oi
    LIMIT 1
  ");
  $stmt->bindValue(':oid', $oid, PDO::PARAM_INT);
  $stmt->bindValue(':oi', $oi, PDO::PARAM_STR);
  $stmt->execute();
  $row = $stmt->fetch(PDO::FETCH_ASSOC);
  return is_array($row);
}
