<?php

namespace App\Services;

use App\Jobs\SendTicketSmsNotificationJob;
use App\Jobs\SendTicketWhatsappNotificationJob;
use App\Models\Setting;
use App\Models\SmsTemplate;
use App\Models\Ticket;
use App\Notifications\TicketAutoClosedNotification;
use App\Notifications\TicketCustomerReplyReminderNotification;
use App\Notifications\TicketRepliedToCustomerNotification;
use App\Notifications\TicketStatusChangedNotification;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;

class TicketNotificationService
{
    public function notifyAdminsForNewTicket(Ticket $ticket): void
    {
        $this->logTicketEvent('ticket.created', $ticket, 'admin_staff');
    }

    public function notifyCustomerForReply(Ticket $ticket, array $context = []): void
    {
        $ticket = $ticket->loadMissing(['customer', 'order']);
        if (!$ticket->customer) {
            return;
        }

        $event = 'ticket.reply.admin';
        if (!$this->acquireEventLock($ticket, $event, $context)) {
            return;
        }

        if ($this->isWebEnabled() && $this->isEventEnabled('reply')) {
            $ticket->customer->notify(new TicketRepliedToCustomerNotification($ticket));
        }

        if ($this->isSmsEnabled() && $this->isEventEnabled('reply')) {
            SendTicketSmsNotificationJob::dispatch($ticket->id, $event, $context);
        }

        if ($this->isWhatsappEnabled() && $this->isEventEnabled('reply')) {
            SendTicketWhatsappNotificationJob::dispatch($ticket->id, $event, $context);
        }

        $this->logTicketEvent($event, $ticket, 'customer');
    }

    public function notifyCustomerForStatus(Ticket $ticket, array $context = []): void
    {
        $ticket = $ticket->loadMissing(['customer', 'order']);
        if (!$ticket->customer) {
            return;
        }

        $event = 'ticket.status.changed';
        if (!$this->acquireEventLock($ticket, $event, $context)) {
            return;
        }

        if ($this->isWebEnabled() && $this->isEventEnabled('status')) {
            $ticket->customer->notify(new TicketStatusChangedNotification($ticket));
        }

        if ($this->isSmsEnabled() && $this->isEventEnabled('status')) {
            SendTicketSmsNotificationJob::dispatch($ticket->id, $event, $context);
        }

        if ($this->isWhatsappEnabled() && $this->isEventEnabled('status')) {
            SendTicketWhatsappNotificationJob::dispatch($ticket->id, $event, $context);
        }

        $this->logTicketEvent($event, $ticket, 'customer');
    }

    public function notifyCustomerForInactivityReminder(Ticket $ticket): void
    {
        $ticket = $ticket->loadMissing(['customer']);
        if (!$ticket->customer || !$this->isWebEnabled()) {
            return;
        }

        $ticket->customer->notify(new TicketCustomerReplyReminderNotification($ticket));
        $this->logTicketEvent('ticket.customer.reply.reminder', $ticket, 'customer');
    }

    public function notifyCustomerForAutoClose(Ticket $ticket): void
    {
        $ticket = $ticket->loadMissing(['customer']);
        if (!$ticket->customer || !$this->isWebEnabled()) {
            return;
        }

        $ticket->customer->notify(new TicketAutoClosedNotification($ticket));
        $this->logTicketEvent('ticket.auto.closed', $ticket, 'customer');
    }

    public function sendSmsForCustomerEvent(Ticket $ticket, string $event, array $context = []): void
    {
        try {
            $templateIdentifier = $event === 'ticket.reply.admin'
                ? 'ticket_reply_customer'
                : 'ticket_status_customer';

            $template = SmsTemplate::query()
                ->where('identifier', $templateIdentifier)
                ->where('is_active', true)
                ->first();

            if (!$template || !$ticket->customer?->mobile) {
                return;
            }

            $smsService = new SendSmsService();
            $mobile = $smsService->normalizeIndianMobile((string) $ticket->customer->mobile);
            if ($mobile === '') {
                return;
            }

            $message = (string) $template->body;
            $replacements = [
                '[[ticket_id]]' => (string) $ticket->id,
                '[[order_id]]' => (string) $ticket->order_id,
                '[[status]]' => $ticket->statusLabel(),
                '[[ticket_url]]' => route('customer.tickets.show', $ticket),
                '[[customer_name]]' => (string) ($ticket->customer->name ?? ''),
            ];
            $message = str_replace(array_keys($replacements), array_values($replacements), $message);

            $smsService->send(
                $mobile,
                $message,
                $template->template_id,
                $smsService->buildVariablesValues((string) $template->body, $replacements),
                $templateIdentifier
            );
        } catch (\Throwable $e) {
            Log::warning('Ticket SMS notification failed', [
                'ticket_id' => $ticket->id,
                'event' => $event,
                'error' => $e->getMessage(),
                'context' => $context,
            ]);
            throw $e;
        }
    }

    public function sendWhatsappForCustomerEvent(Ticket $ticket, string $event, array $context = []): void
    {
        try {
            if (!Schema::hasTable('whatsapp_templates')) {
                return;
            }

            $templateIdentifier = $event === 'ticket.reply.admin'
                ? 'ticket_reply_customer'
                : 'ticket_status_customer';

            $template = DB::table('whatsapp_templates')
                ->where('identifier', $templateIdentifier)
                ->when(Schema::hasColumn('whatsapp_templates', 'is_active'), fn ($query) => $query->where('is_active', 1))
                ->first();

            if (!$template || !$ticket->customer?->mobile || !$ticket->order) {
                return;
            }

            $siteName = ucwords(Setting::get('site_name', env('APP_NAME', 'KiyoKart')));
            $templateName = $templateIdentifier;
            $templateLanguage = 'en_US';
            $data = [
                'phone_number' => $ticket->customer->mobile,
                'sender_name' => $siteName,
                'template_name' => $templateName,
                'template_language' => $templateLanguage,
                'contact_first_name' => ucwords((string) $ticket->customer->name),
                'contact_email' => (string) ($ticket->customer->email ?? ''),
                'contact_groups' => $siteName,
                'contact_country' => 'India',
                'contact_language' => $templateLanguage,
                'whatsapp_template' => $templateIdentifier,
            ];

            if ($templateIdentifier === 'ticket_reply_customer') {
                $data['field_1'] = (string) $ticket->id;
                $data['field_2'] = $siteName;
            } else {
                $data['field_1'] = ucwords((string) $ticket->customer->name);
                $data['field_2'] = (string) $ticket->id;
                $data['field_3'] = $ticket->statusLabel();
                $data['field_4'] = route('customer.tickets.show', $ticket);
                $data['field_5'] = $siteName;
            }

            (new SendWhatsAppService())->sendWhatsApp($ticket->customer->mobile, $siteName, $data, $ticket->order);
        } catch (\Throwable $e) {
            Log::warning('Ticket WhatsApp notification failed', [
                'ticket_id' => $ticket->id,
                'event' => $event,
                'error' => $e->getMessage(),
                'context' => $context,
            ]);
            throw $e;
        }
    }

    private function isWebEnabled(): bool
    {
        return Setting::get('tickets_notify_web', '1') === '1' && Schema::hasTable('notifications');
    }

    private function isSmsEnabled(): bool
    {
        return Setting::get('tickets_notify_sms', '1') === '1';
    }

    private function isWhatsappEnabled(): bool
    {
        return Setting::get('tickets_notify_whatsapp', '0') === '1';
    }

    private function isEventEnabled(string $event): bool
    {
        if ($event === 'reply') {
            return Setting::get('tickets_notify_on_reply', '1') === '1';
        }

        return Setting::get('tickets_notify_on_status', '1') === '1';
    }

    private function acquireEventLock(Ticket $ticket, string $event, array $context = []): bool
    {
        $key = sprintf(
            'ticket-notify:%s:%s:%s',
            $ticket->id,
            $event,
            sha1(json_encode($context))
        );

        return Cache::add($key, true, now()->addMinutes(5));
    }

    private function logTicketEvent(string $event, Ticket $ticket, string $recipientType): void
    {
        Log::info('Ticket notification event', [
            'event' => $event,
            'recipient_type' => $recipientType,
            'ticket_id' => $ticket->id,
            'order_id' => $ticket->order_id,
            'customer_id' => $ticket->customer_id,
            'status' => $ticket->status,
            'last_replied_by' => $ticket->last_replied_by,
        ]);
    }
}
