<?php

namespace App\Jobs;

use App\Models\AiAutomationSettings;
use App\Models\Ticket;
use App\Models\TicketReply;
use App\Models\TicketReplyBlocklist;
use App\Services\AuditLogger;
use App\Services\Whmcs\AgentRotator;
use App\Services\Whmcs\HumanizedReplyDrafter;
use App\Services\Whmcs\WhmcsClient;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

/**
 * Politely nudges a customer who's been silent on a ticket where staff
 * already replied. Uses the existing HumanizedReplyDrafter with an
 * explicit instruction so the message reads like a real follow-up and not
 * a templated "your ticket is still open" robot ping.
 *
 * Tracked per-ticket via tickets.nudge_count + last_nudge_at. The
 * scheduler in routes/console.php picks eligible tickets and dispatches
 * one of these per ticket every nudge_interval_hours, capped at
 * nudge_max_count.
 */
class NudgeWaitingCustomer implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public int $ticketId) {}

    public function handle(HumanizedReplyDrafter $drafter, WhmcsClient $whmcs): void
    {
        $ticket = Ticket::find($this->ticketId);
        if (! $ticket) return;

        $settings = AiAutomationSettings::current();
        if (! $settings->nudge_waiting_customer_enabled) return;
        if ($ticket->nudge_count >= $settings->nudge_max_count) return;
        if (TicketReplyBlocklist::blocks($ticket)) return;

        // Re-check eligibility — customer may have replied between the
        // scheduler picking this row and the job running.
        $lastReply = $ticket->replies()->orderByDesc('sent_at')->first();
        if ($lastReply && $lastReply->author_type === 'customer') {
            Log::info('hsap.nudge.skipped_customer_replied', ['ticket' => $ticket->id]);
            return;
        }

        $nudgeNumber = $ticket->nudge_count + 1;
        $isLastNudge = $nudgeNumber >= $settings->nudge_max_count;

        $instruction = $this->buildInstruction($nudgeNumber, $isLastNudge);

        try {
            // mode='nudge' tells the drafter to skip ticket-state side
            // effects (status flip, ai_draft_reply persist, router,
            // hold-for-review). A nudge is a follow-up, not a new draft.
            $result = $drafter->draft($ticket, $instruction, 'nudge');
            $body = $result['draft'] ?? '';
            if (! $body) return;
        } catch (\Throwable $e) {
            Log::warning('hsap.nudge.draft_failed', [
                'ticket' => $ticket->id, 'err' => $e->getMessage(),
            ]);
            return;
        }

        // Post directly to WHMCS as the rotated agent — bypasses
        // AutoReplyTicket because nudges have their own gate logic. The
        // master gate is nudge_waiting_customer_enabled (checked at the
        // top of handle()); the legacy send_enabled config was a hidden
        // second gate that confused operators and is no longer consulted.
        $agent = AgentRotator::pickForTicket($ticket->id);

        // adminusername MUST be a real WHMCS admin username, not the
        // display name (WHMCS won't resolve "Ayesha Rahman" to an admin
        // → posts unattributed/hidden). Same fix as AutoReplyTicket.
        $adminUsername = $agent['whmcs_admin_username'] ?: $agent['display_name'];
        $posted = $whmcs->addTicketReply(
            $ticket->whmcs_ticket_id,
            $body,
            $adminUsername,
        );
        if ($posted === null) {
            Log::warning('hsap.nudge.whmcs_post_failed', ['ticket' => $ticket->id]);
            return;
        }

        // Local reply row for the timeline.
        TicketReply::create([
            'ticket_id'     => $ticket->id,
            'author_type'   => 'ai_auto',
            'author_name'   => $agent['display_name'],
            'body'          => $body,
            'ai_provider'   => 'nudge',
            'sent_at'       => now(),
        ]);

        $ticket->update([
            'nudge_count'   => $nudgeNumber,
            'last_nudge_at' => now(),
        ]);

        AuditLogger::log('system', 'nudge', 'ai-nudge',
            'ticket.nudge_sent', 'ticket', (string) $ticket->id,
            ['nudge_number' => $nudgeNumber, 'agent' => $agent['display_name']]);
    }

    /**
     * Build the instruction the drafter will follow when composing the
     * nudge. Tone escalates slightly with each nudge — first one is just
     * a check-in; the final one warns the ticket will be auto-closed.
     */
    private function buildInstruction(int $nudgeNumber, bool $isLast): string
    {
        if ($nudgeNumber === 1) {
            return "Write a SHORT (2-3 sentence) friendly check-in. Acknowledge that you replied earlier "
                 . "and ask whether the customer still needs help. Be polite, not pushy. No urgency words. "
                 . "Do NOT recap the original issue — they can scroll up. Just one warm 'are you still there?' note.";
        }
        if ($isLast) {
            return "Write a SHORT (3-4 sentence) final follow-up. Politely say we haven't heard back "
                 . "and will be closing the ticket if there's no response in 24-48 hours. Invite them to "
                 . "reopen anytime if the issue comes up again. Friendly tone, no scolding. Do NOT recap "
                 . "the original issue.";
        }
        return "Write a SHORT (2-3 sentence) follow-up. Politely ask if the previous reply resolved their "
             . "issue and whether they still need help. Stay warm, not pushy. Do NOT recap the original issue.";
    }
}
