<?php

namespace Modules\WhatsApp\Entities\Services;

use Illuminate\Support\Facades\Schema;
use Modules\WhatsApp\Entities\WaAutoReply;
use Modules\WhatsApp\Entities\WaConversation;
use Modules\WhatsApp\Entities\WaMessage;
use Modules\WhatsApp\Entities\WaSetting;

/**
 * The chat workflow: deterministic auto-replies evaluated on each inbound
 * message BEFORE the AI.
 *   1. welcome  — greet on the very first inbound of a conversation
 *   2. keyword  — FAQ-style replies on matched keywords
 *   3. fallback — catch-all when the AI is off and nothing matched
 *
 * Returns whether the pipeline should CONTINUE to the AI. A rule with
 * stop_after halts (so the AI doesn't double-answer). Never runs while a human
 * agent has claimed the conversation.
 */
class WorkflowService
{
    public function handleInbound(WaMessage $inbound, WaConversation $conversation): bool
    {
        if (!Schema::hasTable('wa_auto_replies')) {
            return true;
        }
        // A human is handling this thread — no automation.
        if ($conversation->assigned_user_id) {
            return false;
        }

        $businessId = (int) $inbound->business_id;
        $text = trim((string) $inbound->body);

        $rules = WaAutoReply::where('business_id', $businessId)
            ->where('active', true)->orderBy('priority')->get();
        if ($rules->isEmpty()) {
            return true;
        }

        // 1) Welcome on the first inbound message.
        $inboundCount = WaMessage::where('conversation_id', $conversation->id)->where('direction', 'in')->count();
        if ($inboundCount <= 1) {
            $welcome = $rules->firstWhere('trigger', 'welcome');
            if ($welcome) {
                $this->send($conversation, $welcome);
                if ($welcome->stop_after) {
                    return false;
                }
            }
        }

        // 2) Keyword rules.
        foreach ($rules->where('trigger', 'keyword') as $rule) {
            if ($rule->matches($text)) {
                $this->send($conversation, $rule);
                if ($rule->stop_after) {
                    return false;
                }
                break;
            }
        }

        // 3) Fallback only matters when the AI won't answer.
        $aiOn = WaSetting::get($businessId, 'ai_enabled', '0') === '1';
        if (!$aiOn) {
            $fallback = $rules->firstWhere('trigger', 'fallback');
            if ($fallback) {
                $this->send($conversation, $fallback);
                return false;
            }
        }

        return true;
    }

    private function send(WaConversation $conversation, WaAutoReply $rule): void
    {
        $body = trim($rule->resolveBody());
        if ($body === '') {
            return;
        }

        (new WaSender())->send([
            'business_id' => $conversation->business_id,
            'channel_id'  => $conversation->channel_id,
            'to'          => $conversation->wa_id,
            'body'        => $body,
            'source'      => 'workflow',
        ]);
    }
}
