<?php

namespace Modules\WhatsApp\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use App\Contact;
use Modules\WhatsApp\Entities\Services\ChannelHealthService;
use Modules\WhatsApp\Entities\Services\WaSender;
use Modules\WhatsApp\Entities\WaChannel;
use Modules\WhatsApp\Entities\WaContact;
use Modules\WhatsApp\Entities\WaMessage;

class WaMessageController extends Controller
{
    public function index(Request $request)
    {
        if (!auth()->user()->can('whatsapp.view_messages')) {
            abort(403, 'Unauthorized action.');
        }
        $businessId = request()->session()->get('user.business_id');

        $query = WaMessage::where('business_id', $businessId);

        if ($request->filled('status')) {
            $query->where('status', $request->input('status'));
        }
        if ($request->filled('direction')) {
            $query->where('direction', $request->input('direction'));
        }
        if ($request->filled('channel_id')) {
            $query->where('channel_id', $request->input('channel_id'));
        }
        if ($request->filled('q')) {
            $q = $request->input('q');
            $query->where(function ($w) use ($q) {
                $w->where('wa_id', 'like', "%{$q}%")->orWhere('body', 'like', "%{$q}%");
            });
        }

        $messages = $query->orderByDesc('id')->paginate(50)->withQueryString();
        $channels = WaChannel::where('business_id', $businessId)->pluck('label', 'id');

        // Active templates (with body) for the "insert template" picker in the send modal.
        \Modules\WhatsApp\Entities\Services\DefaultTemplates::ensure($businessId);
        $templates = \Modules\WhatsApp\Entities\WaTemplate::where('business_id', $businessId)
            ->where('active', true)->orderBy('name')->get(['id', 'name', 'body']);

        return view('whatsapp::messages.index', compact('messages', 'channels', 'templates'));
    }

    /**
     * Contact typeahead for the send modal. Returns ERP contacts that have a
     * mobile, EXCLUDING numbers we already know are not on WhatsApp
     * (has_whatsapp = 0). Available (1) and undetermined (null) are kept.
     */
    public function searchContacts(Request $request)
    {
        if (!auth()->user()->can('whatsapp.send_messages')) {
            abort(403, 'Unauthorized action.');
        }
        $businessId = request()->session()->get('user.business_id');
        $q = trim((string) $request->get('q', ''));

        $query = Contact::where('business_id', $businessId)
            ->whereNotNull('mobile')->where('mobile', '!=', '')
            ->whereIn('type', ['customer', 'both']);

        if ($q !== '') {
            $query->where(function ($w) use ($q) {
                $w->where('name', 'like', "%{$q}%")
                  ->orWhere('mobile', 'like', "%{$q}%")
                  ->orWhere('supplier_business_name', 'like', "%{$q}%");
            });
        }

        $contacts = $query->orderBy('name')->limit(30)
            ->get(['id', 'name', 'first_name', 'last_name', 'mobile', 'supplier_business_name']);

        $sender = new WaSender();

        // Map of normalized wa_id => has_whatsapp (raw 0/1/null) for these numbers.
        $waIds = $contacts->map(fn ($c) => $sender->normalize($c->mobile))->filter()->unique()->values();
        $known = WaContact::where('business_id', $businessId)
            ->whereIn('wa_id', $waIds)->pluck('has_whatsapp', 'wa_id');

        $results = [];
        foreach ($contacts as $c) {
            $wa = $sender->normalize($c->mobile);
            if ($wa === '') {
                continue;
            }
            // Skip numbers known to NOT be on WhatsApp.
            if ($known->has($wa) && !is_null($known[$wa]) && (int) $known[$wa] === 0) {
                continue;
            }

            $display = trim((string) $c->name);
            if ($display === '') {
                $display = trim(trim((string) $c->first_name) . ' ' . trim((string) $c->last_name));
            }
            if ($display === '') {
                $display = trim((string) $c->supplier_business_name);
            }
            if ($display === '') {
                $display = $c->mobile;
            }

            $label = $display;
            if (!empty($c->supplier_business_name) && $c->supplier_business_name !== $display) {
                $label .= ' (' . $c->supplier_business_name . ')';
            }
            $label .= ' — ' . $c->mobile;

            // available = known on WhatsApp; otherwise undetermined (never checked).
            $isAvailable = $known->has($wa) && !is_null($known[$wa]) && (int) $known[$wa] === 1;

            $results[] = ['id' => $wa, 'text' => $label, 'mobile' => $wa, 'available' => $isAvailable ? 1 : 0];
        }

        return response()->json(['results' => $results]);
    }

    /** Manual ad-hoc send from the outbox screen. */
    public function store(Request $request)
    {
        if (!auth()->user()->can('whatsapp.send_messages')) {
            abort(403, 'Unauthorized action.');
        }
        $businessId = request()->session()->get('user.business_id');

        $request->validate([
            'to'         => 'required|string|max:30',
            'body'       => 'required|string',
            'channel_id' => 'nullable|integer',
        ]);

        (new WaSender())->send([
            'business_id' => $businessId,
            'channel_id'  => $request->input('channel_id') ?: null,
            'to'          => $request->input('to'),
            'body'        => $request->input('body'),
            'source'      => 'manual',
            'created_by'  => auth()->id(),
        ]);

        return back()->with('status', ['success' => 1, 'msg' => __('whatsapp::lang.saved')]);
    }

    /** Re-queue a single message (e.g. a failed one). */
    public function resend($id)
    {
        if (!auth()->user()->can('whatsapp.send_messages')) {
            abort(403, 'Unauthorized action.');
        }
        $businessId = request()->session()->get('user.business_id');

        $message = WaMessage::where('business_id', $businessId)->findOrFail($id);
        $message->forceFill([
            'status'       => 'pending',
            'error'        => null,
            'available_at' => now(),
        ])->save();

        (new WaSender())->dispatchFor($message);

        return back()->with('status', ['success' => 1, 'msg' => __('whatsapp::lang.resend')]);
    }

    /** Re-drive every pending/queued message (optionally for one channel). */
    public function resendPending(Request $request)
    {
        if (!auth()->user()->can('whatsapp.send_messages')) {
            abort(403, 'Unauthorized action.');
        }
        $businessId = request()->session()->get('user.business_id');

        $health = new ChannelHealthService();
        $total = 0;

        $channelsQuery = WaChannel::where('business_id', $businessId);
        if ($request->filled('channel_id')) {
            $channelsQuery->where('id', $request->input('channel_id'));
        }

        foreach ($channelsQuery->get() as $channel) {
            $total += $health->resendPending($channel);
        }

        return back()->with('status', [
            'success' => 1,
            'msg'     => __('whatsapp::lang.resend_pending') . ": {$total}",
        ]);
    }
}
