<?php
/* ============================================================
   POST api/vote.php  →  تسجيل صوت موظف

   {comp, cat, uid, voter}
   قواعد الحماية:
     • المسابقة يجب أن تكون في حالة "التصويت مفتوح"
     • التصويت مفعّل في الإعدادات ونظامه داخل المنصة
     • لم ينتهِ الموعد
     • صوت واحد لكل فئة لكل ناخب (قيد فريد في قاعدة البيانات)
     • حدّ أقصى للأصوات من نفس الجهاز خلال ساعة
   ============================================================ */

declare(strict_types=1);
require __DIR__ . '/bootstrap.php';
require __DIR__ . '/helpers.php';
require __DIR__ . '/schema.php';

exp_start_session($CONFIG);
exp_require_post();
exp_check_origin();

$b     = exp_body();
$comp  = exp_id($b['comp'] ?? '');
$cat   = exp_id($b['cat'] ?? '');
$uid   = exp_str($b['uid'] ?? '', 64);
$voter = exp_str($b['voter'] ?? '', 100);

if ($comp === '' || $cat === '' || $uid === '') exp_fail('بيانات التصويت ناقصة');

$db = exp_db($CONFIG);

/* ---------- المسابقة وإعداداتها ---------- */
$st = $db->prepare("SELECT status, vote_json, ui_json FROM exp_competitions WHERE id = ? LIMIT 1");
$st->execute([$comp]);
$c = $st->fetch();
if (!$c) exp_fail('المسابقة غير موجودة', 404);

$vote = json_decode((string)($c['vote_json'] ?? ''), true);
$vote = is_array($vote) ? $vote : [];
$ui   = json_decode((string)($c['ui_json'] ?? ''), true);
$ui   = is_array($ui) ? $ui : [];

if (($c['status'] ?? '') !== 'voting')      exp_fail('التصويت غير مفتوح في هذه المسابقة', 403);
if (empty($vote['enabled']))                exp_fail('التصويت مغلق', 403);
if (($vote['system'] ?? 'platform') !== 'platform') exp_fail('التصويت يتم عبر رابط خارجي', 400);
if (array_key_exists('showVote', $ui) && $ui['showVote'] === false) exp_fail('التصويت مخفي', 403);

$deadline = trim((string)($vote['deadline'] ?? ''));
if ($deadline !== '') {
  $ts = strtotime($deadline);
  if ($ts !== false && $ts < time()) exp_fail('انتهى وقت التصويت', 403);
}

/* ---------- هوية الناخب ---------- */
$requireId = !array_key_exists('requireId', $vote) || !empty($vote['requireId']);

if ($requireId) {
  /* الهوية بريد إلكتروني: صوت واحد لكل بريد في كل فئة */
  if ($voter === '') exp_fail('اكتب بريدك الإلكتروني');
  $voter = mb_strtolower(trim($voter));
  if (!filter_var($voter, FILTER_VALIDATE_EMAIL)) {
    exp_fail('اكتب بريدًا إلكترونيًا صحيحًا');
  }

  /* نطاق الشركة إن حُدّد: لا يصوّت إلا من بريده داخل النطاق */
  $domain = mb_strtolower(trim((string)($vote['domain'] ?? '')));
  if ($domain !== '') {
    $domain = ltrim($domain, '@');
    if (!str_ends_with($voter, '@' . $domain)) {
      exp_fail('التصويت مقصور على بريد ' . $domain, 403);
    }
  }

  /* قائمة بريد مسموحة اختيارية */
  $allow = $vote['allowList'] ?? [];
  if (is_array($allow) && $allow) {
    $norm = array_map(fn($x) => mb_strtolower(trim((string)$x)), $allow);
    if (!in_array($voter, $norm, true)) {
      exp_fail('بريدك غير مسجّل في قائمة الناخبين', 403);
    }
  }
  $voterKey = 'em:' . $voter;
} else {
  /* بدون رقم وظيفي: نربط الصوت بالجلسة حتى لا يتكرر من نفس المتصفح */
  if (empty($_SESSION['voter_token'])) $_SESSION['voter_token'] = bin2hex(random_bytes(16));
  $voterKey = 'tok:' . $_SESSION['voter_token'];
}

/* ---------- المرشح ينتمي فعلًا لهذه الفئة ---------- */
$st = $db->prepare("SELECT id, name FROM exp_candidates
                     WHERE comp_id = ? AND uid = ? AND cat_id = ? LIMIT 1");
$st->execute([$comp, $uid, $cat]);
$cand = $st->fetch();
if (!$cand) exp_fail('المرشح غير موجود في هذه الفئة', 404);

/* ---------- حدّ من نفس عنوان الشبكة ----------
   موظفو الشركة كلهم يخرجون من عنوان واحد، فالحدّ مرتفع عمدًا:
   منع التكرار الحقيقي يقوم به القيد الفريد أدناه، وهذا للإساءة الجماعية فقط.
   اضبطه من config.php ← security.max_votes_per_hour
   --------------------------------------------- */
$ip     = exp_client_ip();
$ipCap  = (int)($CONFIG['security']['max_votes_per_hour'] ?? 600);
$st = $db->prepare("SELECT COUNT(*) n FROM exp_votes
                     WHERE ip = ? AND created_at > (NOW() - INTERVAL 1 HOUR)");
$st->execute([$ip]);
if ($ipCap > 0 && (int)$st->fetch()['n'] >= $ipCap) {
  exp_fail('عدد كبير جدًا من الأصوات من هذه الشبكة — حاول بعد قليل', 429);
}

/* ---------- التسجيل ---------- */
try {
  $ins = $db->prepare("INSERT INTO exp_votes (comp_id, cat_id, cand_uid, voter_key, ip)
                       VALUES (?,?,?,?,?)");
  $ins->execute([$comp, $cat, $uid, $voterKey, $ip]);
} catch (PDOException $e) {
  if (($e->errorInfo[1] ?? 0) === 1062) {   // القيد الفريد
    exp_fail('سبق أن صوّتّ في هذه الفئة', 409);
  }
  error_log('vote.php: ' . $e->getMessage());
  exp_fail('تعذّر تسجيل الصوت', 500);
}

/* ---------- النتيجة المحدّثة لهذه الفئة ---------- */
$st = $db->prepare("SELECT cand_uid, COUNT(*) n FROM exp_votes
                     WHERE comp_id = ? AND cat_id = ? GROUP BY cand_uid");
$st->execute([$comp, $cat]);
$tally = [];
foreach ($st as $r) $tally[$r['cand_uid']] = (int)$r['n'];

exp_json([
  'ok'    => true,
  'name'  => $cand['name'],
  'tally' => $tally,
  'total' => array_sum($tally),
]);
