<?php
/**
 * AlertRules — configurable alert thresholds and notification routing.
 *
 * A rule is (kind + threshold_json + notify_channels + scope). The alerts
 * engine (Alerts::evaluate + cron/tick.php) iterates rules matching each
 * incoming position/event and emits an alerts row + queues SMS/email.
 *
 * Threshold shapes by kind (all optional unless noted):
 *   over_speed              {speed_kph:80}                          — required
 *   fuel_drop               {drop_l:20, within_min:10}              — required
 *   ignition_after_hours    {hour_from:20, hour_to:5}               — required, local time
 *   device_offline          {offline_minutes:30}                    — required
 *   geofence_enter/exit     {}                                      — scope_geofence_ids picks fences
 *   idle_too_long           {idle_minutes:15}                       — required
 */
class AlertRules extends Model
{
    private function s($v): string { return trim((string)$v); }

    public function listAll(): array
    {
        return (new DB())->mySelect(
            "SELECT c0d, name, kind, severity, threshold_json, scope_truck_ids, scope_geofence_ids,
                    cooldown_minutes, notify_sms_to, notify_email_to, notify_inapp, active, notes
               FROM alert_rules
              WHERE deleted = 0 AND tenant_id = :tenant
           ORDER BY active DESC, kind ASC, severity DESC",
            [':tenant' => defined('DEFAULT_TENANT_ID') ? DEFAULT_TENANT_ID : 1]
        ) ?: [];
    }

    public function byId(int $id): array
    {
        $rs = (new DB())->mySelect(
            "SELECT * FROM alert_rules WHERE c0d = :id AND deleted = 0 LIMIT 1",
            [':id' => $id]
        );
        return $rs[0] ?? [];
    }

    public function activeByKind(string $kind): array
    {
        return (new DB())->mySelect(
            "SELECT * FROM alert_rules
              WHERE deleted = 0 AND active = 1 AND kind = :k AND tenant_id = :tenant",
            [':k' => $kind, ':tenant' => defined('DEFAULT_TENANT_ID') ? DEFAULT_TENANT_ID : 1]
        ) ?: [];
    }

    public function create(array $d, int $uid): array
    {
        $name = $this->s($d['name'] ?? '');
        $kind = $this->s($d['kind'] ?? '');
        if ($name === '' || $kind === '') return ['ok' => false, 'msg' => 'Name and kind are required.', 'id' => 0];

        $r = (new DB())->insertUpdate(
            "INSERT INTO alert_rules
                (tenant_id, name, kind, severity, threshold_json, scope_truck_ids, scope_geofence_ids,
                 cooldown_minutes, notify_sms_to, notify_email_to, notify_inapp, active, notes, created_by, created_on)
             VALUES
                (:tenant, :name, :kd, :sv, :th, :st, :sg,
                 :cd, :sms, :em, :ia, :ac, :notes, :uid, NOW())",
            [
                ':tenant' => defined('DEFAULT_TENANT_ID') ? DEFAULT_TENANT_ID : 1,
                ':name' => $name,
                ':kd'   => $kind,
                ':sv'   => $this->s(($d['severity'] ?? '') ?: 'medium'),
                ':th'   => $this->s($d['threshold_json'] ?? '') ?: null,
                ':st'   => $this->s($d['scope_truck_ids']    ?? '') ?: null,
                ':sg'   => $this->s($d['scope_geofence_ids'] ?? '') ?: null,
                ':cd'   => max(0, (int)($d['cooldown_minutes'] ?? 15)),
                ':sms'  => $this->s($d['notify_sms_to']   ?? '') ?: null,
                ':em'   => $this->s($d['notify_email_to'] ?? '') ?: null,
                ':ia'   => !empty($d['notify_inapp']) ? 1 : 0,
                ':ac'   => !empty($d['active']) ? 1 : 0,
                ':notes'=> $this->s($d['notes'] ?? ''),
                ':uid'  => $uid,
            ]
        );
        return ['ok' => $r['success'] > 0, 'msg' => 'Rule created.', 'id' => (int)$r['last_id']];
    }

    public function update(int $id, array $d, int $uid): array
    {
        (new DB())->insertUpdate(
            "UPDATE alert_rules SET
                name = :name, kind = :kd, severity = :sv,
                threshold_json = :th, scope_truck_ids = :st, scope_geofence_ids = :sg,
                cooldown_minutes = :cd,
                notify_sms_to = :sms, notify_email_to = :em, notify_inapp = :ia,
                active = :ac, notes = :notes,
                edited_by = :uid, edited_on = NOW()
              WHERE c0d = :id AND deleted = 0",
            [
                ':name' => $this->s($d['name'] ?? ''),
                ':kd'   => $this->s($d['kind'] ?? ''),
                ':sv'   => $this->s(($d['severity'] ?? '') ?: 'medium'),
                ':th'   => $this->s($d['threshold_json'] ?? '') ?: null,
                ':st'   => $this->s($d['scope_truck_ids']    ?? '') ?: null,
                ':sg'   => $this->s($d['scope_geofence_ids'] ?? '') ?: null,
                ':cd'   => max(0, (int)($d['cooldown_minutes'] ?? 15)),
                ':sms'  => $this->s($d['notify_sms_to']   ?? '') ?: null,
                ':em'   => $this->s($d['notify_email_to'] ?? '') ?: null,
                ':ia'   => !empty($d['notify_inapp']) ? 1 : 0,
                ':ac'   => !empty($d['active']) ? 1 : 0,
                ':notes'=> $this->s($d['notes'] ?? ''),
                ':uid'  => $uid,
                ':id'   => $id,
            ]
        );
        return ['ok' => true, 'msg' => 'Rule updated.'];
    }

    public function toggleActive(int $id, int $uid): array
    {
        (new DB())->insertUpdate(
            "UPDATE alert_rules SET active = 1 - active, edited_by = :uid, edited_on = NOW() WHERE c0d = :id",
            [':uid' => $uid, ':id' => $id]
        );
        return ['ok' => true];
    }

    public function softDelete(int $id, int $uid): array
    {
        (new DB())->insertUpdate(
            "UPDATE alert_rules SET deleted = 1, edited_by = :uid, edited_on = NOW() WHERE c0d = :id",
            [':uid' => $uid, ':id' => $id]
        );
        return ['ok' => true];
    }
}
