<?php
declare(strict_types=1);

namespace App\Modules\Notifications\Models;

use App\Core\App;
use App\Core\Model;

class ScheduledNotification extends Model
{
    protected static string $table = 'scheduled_notifications';
    protected static array $fillable = [
        'trigger_code',
        'recipient_type',
        'recipient_id',
        'recipient_phone',
        'message',
        'scheduled_at',
        'sent_at',
        'status',
        'attempts',
        'max_attempts',
        'error_message',
        'context_json',
    ];
    protected static bool $timestamps = true;
    protected static bool $softDelete = false;
    protected static bool $dispatchEvents = false;
    protected static bool $auditEnabled = false;
    protected static bool $autoTrackAuthor = false;

    /**
     * Get all pending notifications ready to send.
     */
    public static function getPending(int $limit = 100): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM scheduled_notifications
             WHERE status = 'pending'
               AND scheduled_at <= NOW()
               AND attempts < max_attempts
             ORDER BY scheduled_at ASC
             LIMIT ?",
            [$limit]
        );
    }

    /**
     * Mark a notification as sent.
     */
    public static function markSent(int $id): void
    {
        $db = App::getInstance()->db();
        $db->update('scheduled_notifications', [
            'status'  => 'sent',
            'sent_at' => date('Y-m-d H:i:s'),
        ], '`id` = ?', [$id]);
    }

    /**
     * Mark a notification as failed (increment attempts).
     */
    public static function markFailed(int $id, string $errorMessage): void
    {
        $db = App::getInstance()->db();
        $db->query(
            "UPDATE scheduled_notifications
             SET attempts = attempts + 1,
                 error_message = ?,
                 status = IF(attempts + 1 >= max_attempts, 'failed', 'pending'),
                 updated_at = NOW()
             WHERE id = ?",
            [$errorMessage, $id]
        );
    }

    /**
     * Cancel notifications matching trigger code and context criteria.
     */
    public static function cancelByContext(string $triggerCode, array $contextMatch): int
    {
        $db = App::getInstance()->db();

        // Build JSON conditions for context matching
        $conditions = ["trigger_code = ?", "status = 'pending'"];
        $params = [$triggerCode];

        foreach ($contextMatch as $key => $value) {
            $conditions[] = "JSON_EXTRACT(context_json, ?) = ?";
            $params[] = '$.' . $key;
            $params[] = is_int($value) ? (string) $value : $value;
        }

        $where = implode(' AND ', $conditions);
        $stmt = $db->query(
            "UPDATE scheduled_notifications SET status = 'cancelled', updated_at = NOW() WHERE {$where}",
            $params
        );

        return $stmt->rowCount();
    }

    /**
     * Check if a notification already exists for this trigger/recipient/date.
     */
    public static function existsForRecipient(string $triggerCode, string $recipientType, int $recipientId, string $date): bool
    {
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT 1 FROM scheduled_notifications
             WHERE trigger_code = ?
               AND recipient_type = ?
               AND recipient_id = ?
               AND DATE(scheduled_at) = ?
               AND status IN ('pending', 'sent')
             LIMIT 1",
            [$triggerCode, $recipientType, $recipientId, $date]
        );
        return $row !== null;
    }

    /**
     * Get recent scheduled notifications for admin display.
     */
    public static function getRecent(int $limit = 50): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM scheduled_notifications ORDER BY created_at DESC LIMIT ?",
            [$limit]
        );
    }
}
