<?php
// cron/hr_leaves_notify_employee.php (FIXED FULL)
// - لا يحدّث notified_employee_at إلا بعد نجاح الإرسال فعليًا
// - Row lock لمنع التكرار
// - يسجل OK/FAIL/EXCEPTION في log
// - لا يعتمد على Session (كرون)
// - يتحقق من decided_at (اختياري) + يتأكد أن البريد موجود/صحيح
declare(strict_types=1);

require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/mailer.php';
require_once __DIR__ . '/../inc/hr_leave_notifications.php';

function notify_log_path(): string {
  // وحّد مسار اللوق: نفس لوق المرسل لو موجود، وإلا لوق داخل cron
  if (function_exists('mail_log_path')) return mail_log_path();
  return __DIR__ . '/cron_mail_error.log';
}
function log_line(string $msg): void {
  @file_put_contents(notify_log_path(), date('Y-m-d H:i:s') . " {$msg}\n", FILE_APPEND);
}

$sent = 0;
$failed = 0;

try {
  $pdo = db();
  if (!$pdo instanceof PDO) throw new RuntimeException('db() did not return PDO');
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (Throwable $e) {
  http_response_code(500);
  log_line("notify_employee BOOT_FAIL err=" . $e->getMessage());
  echo "notify_employee sent=0 failed=1\n";
  exit;
}

// تأكد أن الأعمدة موجودة لتجنب أخطاء صامتة
function has_col(PDO $pdo, string $table, string $col): bool {
  static $cache = [];
  $k = $table;
  if (!isset($cache[$k])) {
    $st = $pdo->query("SHOW COLUMNS FROM `{$table}`");
    $cache[$k] = $st->fetchAll(PDO::FETCH_COLUMN, 0);
  }
  return in_array($col, $cache[$k], true);
}

$hasNotified = false;
$hasDecidedAt = false;
try {
  $hasNotified = has_col($pdo, 'leave_requests', 'notified_employee_at');
  $hasDecidedAt = has_col($pdo, 'leave_requests', 'decided_at');
  if (!$hasNotified) {
    throw new RuntimeException("Column leave_requests.notified_employee_at not found");
  }
} catch (Throwable $e) {
  log_line("notify_employee SCHEMA_FAIL err=" . $e->getMessage());
  echo "notify_employee sent=0 failed=1\n";
  exit;
}

try {
  // الأفضل فلترة decided_at إن كان العمود موجود (لمنع إرسال قبل اتخاذ القرار)
  $sql = "
    SELECT id
    FROM leave_requests
    WHERE status IN ('APPROVED','REJECTED','CANCELLED')
      AND notified_employee_at IS NULL
  ";
  if ($hasDecidedAt) $sql .= " AND decided_at IS NOT NULL ";
  $sql .= " ORDER BY id ASC LIMIT 50";

  $st = $pdo->prepare($sql);
  $st->execute();
  $ids = $st->fetchAll(PDO::FETCH_COLUMN, 0);
} catch (Throwable $e) {
  log_line("notify_employee QUERY_FAIL err=" . $e->getMessage());
  echo "notify_employee sent=0 failed=1\n";
  exit;
}

if (!function_exists('send_leave_status_to_employee')) {
  log_line("notify_employee BOOT_FAIL err=send_leave_status_to_employee_not_found");
  echo "notify_employee sent=0 failed=1\n";
  exit;
}

foreach ($ids as $id) {
  $id = (int)$id;
  if ($id <= 0) continue;

  try {
    $pdo->beginTransaction();

    // Lock row + تأكد ما انرسل أثناء التنفيذ
    $lockSql = "SELECT notified_employee_at FROM leave_requests WHERE id=? FOR UPDATE";
    if ($hasDecidedAt) $lockSql = "SELECT notified_employee_at, decided_at FROM leave_requests WHERE id=? FOR UPDATE";

    $lock = $pdo->prepare($lockSql);
    $lock->execute([$id]);
    $row = $lock->fetch();

    if (!$row) {
      $pdo->rollBack();
      $failed++;
      log_line("notify_employee FAIL id={$id} err=leave_not_found_after_lock");
      continue;
    }

    if (!empty($row['notified_employee_at'])) {
      $pdo->commit();
      continue;
    }

    if ($hasDecidedAt && empty($row['decided_at'])) {
      $pdo->rollBack();
      $failed++;
      log_line("notify_employee FAIL id={$id} err=decided_at_missing");
      continue;
    }

    // إرسال بريد الموظف (يفضل أن الدالة تجلب البريد من users.email أو employees.email)
    $res = send_leave_status_to_employee($pdo, $id);

    if (!empty($res['ok'])) {
      $up = $pdo->prepare("UPDATE leave_requests SET notified_employee_at=NOW() WHERE id=? AND notified_employee_at IS NULL");
      $up->execute([$id]);

      $pdo->commit();

      $sent++;
      $to = (string)($res['to'] ?? $res['email'] ?? '');
      $via = (string)($res['via'] ?? '');
      $mid = (string)($res['mid'] ?? '');
      log_line("notify_employee OK id={$id} to={$to} via={$via} mid={$mid}");
    } else {
      $pdo->rollBack();

      $failed++;
      $err = (string)($res['err'] ?? $res['msg'] ?? 'unknown');
      $to  = (string)($res['to'] ?? $res['email'] ?? '');
      log_line("notify_employee FAIL id={$id} to={$to} err={$err}");
    }
  } catch (Throwable $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    $failed++;
    log_line("notify_employee EXCEPTION id={$id} err=" . $e->getMessage());
  }
}

echo "notify_employee sent={$sent} failed={$failed}\n";