<?php

namespace App\Services;

use App\Models\SupportTicket;
use App\Models\TicketAgent;
use App\Models\Lead;
use Illuminate\Support\Facades\Log;

class TicketRoutingService
{
    /**
     * Auto-assign a ticket to the best available agent
     */
    public function autoAssignTicket(SupportTicket $ticket)
    {
        // Get available agents for this device
        $availableAgents = TicketAgent::available()
            ->forDevice($ticket->device_id)
            ->with('user')
            ->get();

        if ($availableAgents->isEmpty()) {
            Log::info("No available agents for ticket {$ticket->ticket_number}");
            return false;
        }

        // Find the best agent using load balancing
        $bestAgent = $this->selectBestAgent($availableAgents, $ticket);

        if ($bestAgent) {
            $ticket->assignToAgent($bestAgent->user_id);
            Log::info("Auto-assigned ticket {$ticket->ticket_number} to agent {$bestAgent->user->name}");
            return true;
        }

        return false;
    }

    /**
     * Select the best agent based on various criteria
     */
    protected function selectBestAgent($agents, SupportTicket $ticket)
    {
        // Strategy 1: Round-robin with load balancing
        // Find agent with lowest current ticket count
        $bestAgent = $agents->sortBy('current_tickets')->first();

        // Strategy 2: Priority-based assignment
        // If ticket is urgent, assign to supervisor or experienced agent
        if ($ticket->priority === 'urgent') {
            $supervisor = $agents->where('role', 'supervisor')->first();
            if ($supervisor && $supervisor->isAvailable()) {
                return $supervisor;
            }
        }

        // Strategy 3: Category/expertise matching (if permissions include categories)
        if ($ticket->category) {
            $expertAgent = $agents->filter(function ($agent) use ($ticket) {
                return $this->hasExpertise($agent, $ticket->category);
            })->sortBy('current_tickets')->first();

            if ($expertAgent) {
                return $expertAgent;
            }
        }

        return $bestAgent;
    }

    /**
     * Check if agent has expertise in a category
     */
    protected function hasExpertise(TicketAgent $agent, $category)
    {
        if (!$agent->permissions) {
            return true; // Agent can handle all categories
        }

        // Check if permissions include the category
        return in_array($category, $agent->permissions) || 
               in_array('all_categories', $agent->permissions);
    }

    /**
     * Reassign tickets when an agent goes offline
     */
    public function reassignAgentTickets($agentId, $deviceId)
    {
        // Get all open tickets for this agent
        $tickets = SupportTicket::where('assigned_to', $agentId)
            ->where('device_id', $deviceId)
            ->open()
            ->get();

        $reassignedCount = 0;

        foreach ($tickets as $ticket) {
            if ($this->autoAssignTicket($ticket)) {
                $reassignedCount++;
            }
        }

        Log::info("Reassigned {$reassignedCount} tickets from agent {$agentId}");

        return $reassignedCount;
    }

    /**
     * Balance workload across agents
     */
    public function balanceWorkload($deviceId)
    {
        $agents = TicketAgent::available()
            ->forDevice($deviceId)
            ->get();

        if ($agents->count() < 2) {
            return; // Need at least 2 agents to balance
        }

        // Get unassigned tickets
        $unassignedTickets = SupportTicket::where('device_id', $deviceId)
            ->unassigned()
            ->open()
            ->orderBy('priority', 'desc')
            ->get();

        foreach ($unassignedTickets as $ticket) {
            $this->autoAssignTicket($ticket);
        }
    }

    /**
     * Create a ticket from an incoming WhatsApp message
     */
    public function createTicketFromMessage($deviceId, $customerPhone, $message, $customerName = null)
    {
        // Check if there's already an open ticket for this customer
        $existingTicket = SupportTicket::where('device_id', $deviceId)
            ->where('customer_phone', $customerPhone)
            ->open()
            ->first();

        if ($existingTicket) {
            // Add message to existing ticket
            $existingTicket->addMessage(
                $message,
                'customer',
                null,
                'text'
            );
            return $existingTicket;
        }

        // Create new ticket
        $ticket = SupportTicket::create([
            'device_id' => $deviceId,
            'customer_phone' => $customerPhone,
            'customer_name' => $customerName,
            'subject' => 'WhatsApp Conversation',
            'description' => $message,
            'status' => 'new',
            'priority' => $this->calculatePriority($message),
            'category' => 'whatsapp',
        ]);

        // Add initial message
        $ticket->addMessage(
            $message,
            'customer',
            null,
            'text'
        );

        // Create or update lead
        $this->createOrUpdateLead($deviceId, $customerPhone, $customerName, $ticket);

        // Auto-assign if enabled
        $this->autoAssignTicket($ticket);

        Log::info("Created ticket {$ticket->ticket_number} from WhatsApp message");

        return $ticket;
    }

    /**
     * Calculate ticket priority based on message content
     */
    protected function calculatePriority($message)
    {
        $urgentKeywords = ['urgent', 'emergency', 'asap', 'immediately', 'help', 'problem', 'issue'];
        $messageLower = strtolower($message);

        foreach ($urgentKeywords as $keyword) {
            if (strpos($messageLower, $keyword) !== false) {
                return 'high';
            }
        }

        return 'medium';
    }

    /**
     * Create or update lead from ticket
     */
    public function createOrUpdateLead($deviceId, $customerPhone, $customerName, SupportTicket $ticket)
    {
        $lead = Lead::where('device_id', $deviceId)
            ->where('customer_phone', $customerPhone)
            ->first();

        if ($lead) {
            // Update existing lead
            $lead->ticket_id = $ticket->id;
            $lead->last_contact_at = now();
            $lead->updateScore(5); // Increase score for engagement
            
            if (!$lead->customer_name && $customerName) {
                $lead->customer_name = $customerName;
            }
            
            $lead->save();
            $lead->addNote("New ticket created: {$ticket->ticket_number}");
        } else {
            // Create new lead
            $lead = Lead::create([
                'device_id' => $deviceId,
                'customer_phone' => $customerPhone,
                'customer_name' => $customerName,
                'source' => 'whatsapp',
                'status' => 'new',
                'lead_score' => 50,
                'ticket_id' => $ticket->id,
                'last_contact_at' => now(),
            ]);

            $lead->addNote("Lead created from ticket: {$ticket->ticket_number}");
        }

        // Update ticket with lead score
        $ticket->lead_score = $lead->lead_score;
        $ticket->save();

        return $lead;
    }

    /**
     * Get routing statistics
     */
    public function getRoutingStats($deviceId)
    {
        $agents = TicketAgent::forDevice($deviceId)->get();

        $stats = [
            'total_agents' => $agents->count(),
            'online_agents' => $agents->where('status', 'online')->count(),
            'available_agents' => TicketAgent::available()->forDevice($deviceId)->count(),
            'agent_workload' => [],
        ];

        foreach ($agents as $agent) {
            $stats['agent_workload'][] = [
                'name' => $agent->user->name,
                'current_tickets' => $agent->current_tickets,
                'max_tickets' => $agent->max_tickets,
                'utilization' => $agent->max_tickets > 0 
                    ? round(($agent->current_tickets / $agent->max_tickets) * 100, 2) 
                    : 0,
                'status' => $agent->status,
            ];
        }

        return $stats;
    }
}
