<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 * One rule that routes a matching ticket to a specific WHMCS admin and
 * optionally flips status/priority. Walked in (sort_order, id) order by
 * TicketRouter — first match wins.
 */
class TicketRoutingRule extends Model
{
    public const PRIORITY_ORDER = ['low' => 1, 'medium' => 2, 'high' => 3, 'critical' => 4];

    protected $fillable = [
        'name', 'enabled', 'sort_order',
        'match_departments', 'match_keywords', 'match_min_priority', 'match_statuses',
        'target_whmcs_admin', 'target_pool',
        'set_status', 'set_priority', 'append_internal_note',
        'created_by',
    ];

    protected $casts = [
        'enabled'           => 'boolean',
        'match_departments' => 'array',
        'match_statuses'    => 'array',
        'target_pool'       => 'array',
    ];

    /**
     * Pick which WHMCS admin to assign to RIGHT NOW.
     *
     * If the rule has a target_pool (multi-employee shift schedule), find
     * the admin whose shift covers `now` (Asia/Dhaka). Falls back to:
     *   - first pool entry if none on shift
     *   - target_whmcs_admin (legacy single-admin field) if pool is empty
     *
     * Pool item shape:
     *   { "whmcs_admin": "tanvir", "shift_start": "00:00:00",
     *     "shift_end": "08:00:00", "days": ["mon",...], "sort_order": 0 }
     */
    public function pickAdminForNow(): ?string
    {
        $pool = $this->target_pool ?: [];
        if (empty($pool)) return $this->target_whmcs_admin ?: null;

        $now = \Carbon\Carbon::now('Asia/Dhaka');
        $day = strtolower($now->format('D'));

        // Sort by sort_order so ties go to the first-listed admin.
        usort($pool, fn ($a, $b) => ($a['sort_order'] ?? 0) <=> ($b['sort_order'] ?? 0));

        foreach ($pool as $p) {
            $days = $p['days'] ?? \App\Models\AiAutomationSettings::ALL_DAYS;
            if (! in_array($day, $days, true)) continue;

            $start = \Carbon\Carbon::createFromFormat('H:i:s', $p['shift_start'] ?? '09:00:00', 'Asia/Dhaka')
                           ->setDate($now->year, $now->month, $now->day);
            $end   = \Carbon\Carbon::createFromFormat('H:i:s', $p['shift_end'] ?? '18:00:00', 'Asia/Dhaka')
                           ->setDate($now->year, $now->month, $now->day);
            $onShift = $end->lt($start)
                ? ($now->gte($start) || $now->lte($end))
                : $now->between($start, $end);

            if ($onShift) return (string) ($p['whmcs_admin'] ?? '');
        }

        // No one on shift — fall back to the first pool entry so the ticket
        // doesn't get orphaned. Their pager/email handles after-hours.
        return (string) ($pool[0]['whmcs_admin'] ?? $this->target_whmcs_admin ?? null);
    }

    /**
     * Does this rule match the given ticket? All configured criteria are
     * AND-ed; unset criteria are treated as "any value matches".
     */
    public function matches(Ticket $ticket): bool
    {
        // Department
        $depts = $this->match_departments ?: [];
        if (! empty($depts) && ! in_array($ticket->department, $depts, true)) {
            return false;
        }

        // Status (WHMCS-side label)
        $statuses = $this->match_statuses ?: [];
        if (! empty($statuses) && ! in_array($ticket->whmcs_status, $statuses, true)) {
            return false;
        }

        // Priority threshold — match when ticket priority is ≥ rule's min.
        if ($this->match_min_priority) {
            $minRank = self::PRIORITY_ORDER[$this->match_min_priority] ?? 1;
            $tRank   = self::PRIORITY_ORDER[strtolower((string) $ticket->priority)] ?? 1;
            if ($tRank < $minRank) return false;
        }

        // Keyword (any keyword present in subject OR body case-insensitively).
        $kw = trim((string) $this->match_keywords);
        if ($kw !== '') {
            $haystack = mb_strtolower(($ticket->subject ?: '') . ' ' . ($ticket->ai_draft_reply ?: ''), 'UTF-8');
            $tokens = array_filter(array_map('trim',
                preg_split('/[,;\n]/', $kw)));
            $hit = false;
            foreach ($tokens as $token) {
                if ($token === '') continue;
                if (str_contains($haystack, mb_strtolower($token, 'UTF-8'))) {
                    $hit = true; break;
                }
            }
            if (! $hit) return false;
        }

        return true;
    }
}
