<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Tenant;
use App\Models\Agent;
use App\Models\Queue;
use App\Models\WaitingList;
use App\Models\DailyMetric;
use Carbon\Carbon;
use App\Events\DashboardUpdate;

class AmiEventController extends Controller
{
    public function handle(Request $request)
    {
        $token = $request->header('X-Tenant-Token');
        $tenant = Tenant::where('api_key', $token)->first();

        if (!$tenant) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        $data = $request->all();
        $eventName = $data['Event'] ?? null;
        $queueNumber = $data['Queue'] ?? null;
        $interface = $data['Interface'] ?? $data['MemberName'] ?? null; // Tenta achar quem é o agente

        if ($queueNumber) {
            $this->saveQueues($queueNumber, $tenant);
        }
        if ($interface) {
            $this->saveAgent($interface, $tenant);
        }

        if (!$eventName || !$queueNumber) {
            return response()->json(['status' => 'ignored']);
        }

        $queue = null;
        if ($queueNumber) {
            $queue = Queue::where('tenant_id', $tenant->id)
                ->where('source_id', $queueNumber)
                ->first();
        }

        // Recupera o Agente (se aplicável)
        $agent = null;
        if ($interface) {
            $agent = Agent::where('tenant_id', $tenant->id)
                ->where('interface', $interface)
                ->first();
        }

        if (!$queue) {
            return response()->json(['error' => 'Fila não encontrada'], 404);
        }


        switch ($eventName) {
            case 'QueueCallerJoin':
                $this->handleJoin($queue, $data);
                break;
            case 'AgentConnect':
                $this->handleConnect($queue, $data);
                break;
            case 'AgentComplete': // Ou QueueCallerLeave com TalkTime
                $this->handleComplete($queue, $data);
                break;
            case 'QueueCallerAbandon':
                $this->handleAbandon($queue, $data);
                break;

            case 'QueueMemberPause':
                if ($agent) $this->handlePause($agent, $data, $tenant->id);
                break;

            case 'AgentRingNoAnswer':
                if ($agent) $this->handleRingNoAnswer($agent, $tenant->id);
                break;
        }

        return response()->json(['status' => 'success']);
    }


    private function handleJoin($queue, $data)
    {
        WaitingList::create([
            'tenant_id' => $queue->tenant_id,
            'queue_id' => $queue->id,
            'caller_number' => $data['CallerIDNum'],
            'caller_name' => $data['CallerIDName'] ?? 'Desconhecido',
            'entered_at' => now(),
        ]);

        $this->updateMetric($queue, 'received_count', 1);
        $this->broadcastUpdate($queue);
    }

    private function handleConnect($queue, $data)
    {
        // 1. Remove da Lista de Espera (Já existente)
        WaitingList::where('queue_id', $queue->id)
            ->where('caller_number', $data['CallerIDNum'])
            ->delete();

        // 2. Atualiza Métricas da Fila (Já existente)
        $metric = $this->getTodayMetric($queue);
        $holdTime = intval($data['HoldTime'] ?? 0);
        $newAvg = (($metric->avg_wait_time * $metric->answered_count) + $holdTime) / ($metric->answered_count + 1);

        $metric->avg_wait_time = $newAvg;
        $metric->answered_count += 1;
        $metric->save();

        // --- NOVO: Atualiza o Agente ---
        $agent = $this->findAgent($queue->tenant_id, $data);
        if ($agent) {
            $agent->status = 'talking'; // Muda cor para Azul
            $agent->last_status_change = now();
            $agent->increment('total_calls_answered'); // KPI pessoal do agente
            $agent->save();
        }
        // -------------------------------

        $this->broadcastUpdate($queue);
    }

    private function handleComplete($queue, $data)
    {
        // 1. Atualiza Métricas da Fila (Já existente)
        $talkTime = intval($data['TalkTime'] ?? 0);
        $metric = $this->getTodayMetric($queue);

        if ($metric->answered_count > 0) {
            $newAvg = (($metric->avg_talk_time * ($metric->answered_count - 1)) + $talkTime) / $metric->answered_count;
            $metric->avg_talk_time = $newAvg;
            $metric->save();
        }

        // --- NOVO: Libera o Agente ---
        $agent = $this->findAgent($queue->tenant_id, $data);
        if ($agent) {
            // Só volta para available se ele não estiver pausado (fluxo simples)
            // O ideal seria checar se ele pausou DURANTE a chamada, mas
            // geralmente ao desligar ele volta a ficar livre.
            $agent->status = 'available'; // Muda cor para Verde
            $agent->last_status_change = now();
            $agent->save();
        }
        // -----------------------------

        $this->broadcastUpdate($queue);
    }

    private function handleAbandon($queue, $data)
    {
        WaitingList::where('queue_id', $queue->id)
            ->where('caller_number', $data['CallerIDNum'])
            ->delete();

        $this->updateMetric($queue, 'abandoned_count', 1);
        $this->broadcastUpdate($queue);
    }

    private function handlePause($agent, $data, $tenantId)
    {
        $isPaused = isset($data['Paused']) && $data['Paused'] == '1';

        // Atualiza o Status ENUM e o Motivo
        $agent->status = $isPaused ? 'paused' : 'available'; // Define se está pausado ou disponível
        $agent->pause_reason = $isPaused ? ($data['Reason'] ?? 'Pausa') : null;
        $agent->last_status_change = now(); // Atualiza o relógio

        $agent->save();

        broadcast(new DashboardUpdate($tenantId));
    }

    private function saveAgent($interface, $tenant)
    {
        $exists = Agent::where('tenant_id', $tenant->id)
            ->where('interface', $interface)
            ->exists();

        if (!$exists) {
            // Tenta limpar o nome. Ex: PJSIP/200 -> 200
            $name = $interface;
            if (strpos($interface, '/') !== false) {
                $parts = explode('/', $interface);
                $name = end($parts);
            }

            Agent::create([
                'tenant_id' => $tenant->id,
                'name' => "Agente $name",
                'interface' => $interface,
                'status' => 'available' // Assume disponível ao ser descoberto
            ]);
        }
    }

    private function getTodayMetric($queue)
    {
        return DailyMetric::firstOrCreate(
            [
                'queue_id' => $queue->id,
                'date' => Carbon::today()
            ],
            [
                'tenant_id' => $queue->tenant_id,
                'received_count' => 0,
                'answered_count' => 0,
                'abandoned_count' => 0
            ]
        );
    }

    private function updateMetric($queue, $field, $value)
    {
        $metric = $this->getTodayMetric($queue);
        $metric->increment($field, $value);
    }

    private function handleRingNoAnswer($agent, $tenantId)
    {
        // Incrementa contador de chamadas perdidas pelo agente
        $agent->increment('total_ring_no_answer');

        broadcast(new DashboardUpdate($tenantId));
    }

    private function saveQueues($queue, $tenant)
    {
        $existingQueue = Queue::where('tenant_id', $tenant->id)
            ->where('source_id', $queue)
            ->exists();

        if (!$existingQueue) {
            Queue::create([
                'tenant_id' => $tenant->id,
                'type' => 'voice',
                'source_id' => $queue,
                'name' => "Fila $queue", // Nome padrão provisório
                'sector' => null // Começa sem setor
            ]);
        }
    }

    // --- COLOQUE AQUI NO FINAL, JUNTO COM OS OUTROS PRIVATES ---
    private function findAgent($tenantId, $data)
    {
        // Tenta achar o identificador do agente no evento
        $interface = $data['Interface'] ?? $data['MemberName'] ?? null;

        if (!$interface) return null;

        return Agent::where('tenant_id', $tenantId)
            ->where('interface', $interface)
            ->first();
    }
    private function broadcastUpdate($queueOrTenantId)
    {
        $tenantId = is_object($queueOrTenantId) ? $queueOrTenantId->tenant_id : $queueOrTenantId;
        broadcast(new DashboardUpdate($tenantId));
    }
}
