<?php
/* ============================================================================
 *  cron/attendance_cron.php — run every minute (or every few minutes) via cron.
 *  Per company schedule (att_rules.extra), it:
 *    • reminds staff to CLOCK IN  10 min before each session start
 *    • reminds staff to CLOCK OUT  5 min after each session end
 *    • AUTO clock-outs staff who forgot, 5 min after each session end,
 *      using the scheduled end time — UNLESS the staff opted in to OT today
 *      (PM session only; morning always auto-closes).
 *  Reminders are de-duplicated (att_reminder_log) so each fires once per day.
 *
 *  SECURITY: call from cron with the key, e.g.
 *    * * * * * php /home/USER/public_html/seven-credit-system/cron/attendance_cron.php
 *  or via URL:  https://7d-lao.com/seven-credit-system/cron/attendance_cron.php?key=7d-cron-2026
 * ==========================================================================*/

define('CRON_KEY', '7d-cron-2026');   // change this; must match the URL/cron call

$isCli = (php_sapi_name() === 'cli');
if (!$isCli && (($_GET['key'] ?? '') !== CRON_KEY)) { http_response_code(403); exit('forbidden'); }

require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/notify.php';
date_default_timezone_set('Asia/Vientiane');

$today   = date('Y-m-d');
$iso     = (int)date('N');                 // 1=Mon .. 7=Sun
$nowMin  = (int)date('G') * 60 + (int)date('i');   // minutes since midnight
function hm2min($hm){ $hm=substr((string)$hm,0,5); if(!$hm||strpos($hm,':')===false) return null; [$h,$m]=explode(':',$hm); return (int)$h*60+(int)$m; }
function minfmt($m){ return sprintf('%02d:%02d', intdiv($m,60), $m%60); }

$REMIND_BEFORE_IN = 10;   // remind to clock in, minutes before start
$REMIND_AFTER_OUT = 5;    // remind to clock out, minutes after end
$WINDOW           = 5;    // reminder fires if now within [target, target+WINDOW) (covers 1–5 min cron)

$log = [];
function logline(&$log,$s){ $log[]=$s; }

/* companies that have an attendance schedule configured */
$companies = $pdo->query("SELECT company_id, extra FROM att_rules")->fetchAll(PDO::FETCH_ASSOC);

foreach ($companies as $crow) {
    $companyId = (int)$crow['company_id'];
    $ex = json_decode($crow['extra'] ?? '', true);
    if (!is_array($ex) || empty($ex['schedule'][$iso])) continue;   // no session today
    $sd = $ex['schedule'][$iso];

    $sessions = [];
    if (!empty($sd['am_start']) && !empty($sd['am_end'])) $sessions['am'] = ['start'=>hm2min($sd['am_start']),'end'=>hm2min($sd['am_end'])];
    if (!empty($sd['pm_start']) && !empty($sd['pm_end'])) $sessions['pm'] = ['start'=>hm2min($sd['pm_start']),'end'=>hm2min($sd['pm_end'])];
    if (!$sessions) continue;

    /* active, non-exempt staff */
    $st = $pdo->prepare("
        SELECT cs.user_id, u.name
        FROM company_staff cs
        JOIN users u ON u.id = cs.user_id AND u.status='active'
        LEFT JOIN att_staff a ON a.company_id = cs.company_id AND a.staff_id = cs.user_id
        WHERE cs.company_id = ? AND COALESCE(a.checkin_required,1) = 1");
    $st->execute([$companyId]);
    $staff = $st->fetchAll(PDO::FETCH_ASSOC);
    if (!$staff) continue;

    /* today's attendance rows keyed by staff */
    $aq = $pdo->prepare("SELECT id, staff_id, am_in, am_out, pm_in, pm_out, hours_worked FROM hr_attendance WHERE company_id=? AND work_date=?");
    $aq->execute([$companyId, $today]);
    $att = [];
    foreach ($aq->fetchAll(PDO::FETCH_ASSOC) as $r) $att[(int)$r['staff_id']] = $r;

    $logHas = $pdo->prepare("SELECT 1 FROM att_reminder_log WHERE staff_id=? AND work_date=? AND kind=? LIMIT 1");
    $logAdd = $pdo->prepare("INSERT IGNORE INTO att_reminder_log (company_id,staff_id,work_date,kind,created_at) VALUES (?,?,?,?,NOW())");

    foreach ($sessions as $sk => $sess) {
        $inField  = $sk.'_in';   $outField = $sk.'_out';
        $remInTarget  = $sess['start'] - $REMIND_BEFORE_IN;
        $remOutTarget = $sess['end']   + $REMIND_AFTER_OUT;

        $inWindow  = ($nowMin >= $remInTarget  && $nowMin < $remInTarget  + $WINDOW);
        $outWindow = ($nowMin >= $remOutTarget && $nowMin < $remOutTarget + $WINDOW);

        foreach ($staff as $s) {
            $uid = (int)$s['user_id'];
            $row = $att[$uid] ?? null;
            $hasIn  = $row && !empty($row[$inField]);
            $hasOut = $row && !empty($row[$outField]);
            $label  = $sk === 'am' ? 'morning' : 'afternoon';

            /* clock-in reminder — only if not yet clocked in for this session */
            if ($inWindow && !$hasIn) {
                $kind = 'rem_'.$inField;
                $logHas->execute([$uid,$today,$kind]);
                if (!$logHas->fetchColumn()) {
                    notify_user($pdo,$uid,"⏰ Time to clock in","Your ".$label." shift starts at ".minfmt($sess['start']).". Please check in.","staff/checkin.php");
                    $logAdd->execute([$companyId,$uid,$today,$kind]);
                    logline($log,"in-reminder $uid $sk");
                }
            }

            /* clock-out reminder — only if clocked in but not out */
            if ($outWindow && $hasIn && !$hasOut) {
                $kind = 'rem_'.$outField;
                $logHas->execute([$uid,$today,$kind]);
                if (!$logHas->fetchColumn()) {
                    notify_user($pdo,$uid,"⏰ Don't forget to clock out","Your ".$label." shift ended at ".minfmt($sess['end']).". Please check out.","staff/checkin.php");
                    $logAdd->execute([$companyId,$uid,$today,$kind]);
                    logline($log,"out-reminder $uid $sk");
                }
            }
        }
    }
}

if (php_sapi_name()==='cli') { echo date('Y-m-d H:i')." — ".count($log)." action(s): ".implode(', ',$log)."\n"; }
else { header('Content-Type: text/plain'); echo "ok ".count($log); }