<?php

namespace App\Services\Whmcs;

use App\Models\SupportAgent;
use Carbon\Carbon;

/**
 * Picks which staff agent identity gets attributed to a given outbound
 * customer reply. Two goals:
 *   1. Same ticket → same agent across replies (consistency — customer
 *      sees a "person" they can address by name).
 *   2. Across the fleet — even spread.
 *
 * Source of truth = `support_agents` DB table (admin-managed via Settings
 * UI). Falls back to the legacy config/hsap-humanizer.php pool only when
 * no enabled rows exist in DB — useful during fresh installs before the
 * admin sets up real personas.
 */
class AgentRotator
{
    public static function pickForTicket(int $ticketId): array
    {
        $agents = SupportAgent::where('enabled', true)
            ->orderBy('sort_order')
            ->orderBy('id')
            ->get();

        if ($agents->isNotEmpty()) {
            $idx = $ticketId % $agents->count();
            return self::toArray($agents[$idx]);
        }

        // Legacy config-based pool — keeps the system working before the
        // admin adds DB-backed agents.
        $configAgents = config('hsap-humanizer.agents', []);
        if (! empty($configAgents)) {
            $idx = $ticketId % count($configAgents);
            return $configAgents[$idx];
        }
        return self::fallbackAgent();
    }

    /**
     * Get the explicit "default" agent (the one the auto-reply ticker uses
     * when no specific agent is chosen). Falls back to first enabled.
     */
    public static function defaultAgent(): array
    {
        $row = SupportAgent::where('enabled', true)
            ->where('is_default', true)
            ->first()
            ?? SupportAgent::where('enabled', true)->orderBy('sort_order')->first();
        if ($row) return self::toArray($row);
        return self::fallbackAgent();
    }

    private static function toArray(SupportAgent $a): array
    {
        return [
            'id'                   => $a->id,
            'display_name'         => $a->display_name,
            'whmcs_admin_username' => $a->whmcs_admin_username,
            // Persona-specific WHMCS API credentials, when configured.
            // The note-posting jobs (AdminNoteAssist / NameserverDiagnostic /
            // EmailDeliverabilityAssist / HumanizedReplyDrafter::postNeedsHumanNote)
            // pass these to addTicketNote so WHMCS attributes the note to
            // the persona instead of the default API user.
            'whmcs_credentials'    => $a->hasOwnApiCredentials()
                ? [
                    'identifier' => (string) $a->whmcs_api_identifier,
                    'secret'     => (string) $a->whmcs_api_secret,
                ]
                : null,
            'header_template'      => $a->effectiveHeader(),
            'footer_template'      => $a->effectiveFooter(),
            'tone_keywords'        => $a->toneList() ?: ['polite', 'concise'],
            'online_hours'         => [(int) $a->online_hour_start, (int) $a->online_hour_end],
            // Legacy field expected by older code paths — built from footer
            // for backwards compat.
            'signature'            => trim($a->effectiveFooter()),
        ];
    }

    /**
     * The agent rotator can also be asked "who's online right now?" — used
     * by the scheduler to decide whether to delay-until-next-shift.
     */
    public static function isOnline(array $agent, ?Carbon $when = null): bool
    {
        $when = $when ?? Carbon::now('Asia/Dhaka');
        $hour = $when->hour;
        [$start, $end] = $agent['online_hours'] ?? [0, 24];
        return $hour >= $start && $hour < $end;
    }

    /**
     * Next moment the given agent is "back online" — used to schedule a
     * reply to look like it was sent first thing in the morning.
     */
    public static function nextOnlineSlot(array $agent, ?Carbon $from = null): Carbon
    {
        $from = ($from ?? Carbon::now('Asia/Dhaka'))->copy();
        [$start, $end] = $agent['online_hours'] ?? [0, 24];

        // Already online → return now.
        if (self::isOnline($agent, $from)) return $from;

        // Same-day morning if we're before the start hour.
        if ($from->hour < $start) {
            return $from->copy()->setTime($start, random_int(2, 18), random_int(0, 59));
        }

        // Past closing — shift to tomorrow's start with a small randomized
        // offset so multiple queued replies don't all land at exactly :00:00.
        return $from->copy()->addDay()->setTime($start, random_int(2, 18), random_int(0, 59));
    }

    private static function fallbackAgent(): array
    {
        return [
            'whmcs_admin_username' => 'support',
            'display_name'         => 'Support Team',
            // Fallback agent never has its own API creds — note posting
            // falls back to the default WHMCS API user (configured in
            // Settings → WHMCS Connection).
            'whmcs_credentials'    => null,
            'signature'            => "Regards,\nHostSeba Support",
            'online_hours'         => [0, 24],
            'tone_keywords'        => ['polite', 'concise'],
        ];
    }
}
