<?php
/**
 * Evolution API - Cliente PHP
 * Sistema de Integração WhatsApp para MontaLoja
 * Documentação: https://doc.evolution-api.com
 */

class EvolutionAPI {
    private $baseUrl;
    private $apiKey;
    private $instanceName;
    
    public function __construct(string $baseUrl, string $apiKey, string $instanceName = 'montaloja') {
        // Sanitizar URL - remover espaços e caracteres invisíveis
        $baseUrl = trim($baseUrl);
        $baseUrl = preg_replace('/\s+/', '', $baseUrl);
        $baseUrl = rtrim($baseUrl, '/');
        
        // Garantir que tem protocolo
        if (!preg_match('/^https?:\/\//', $baseUrl)) {
            $baseUrl = 'http://' . $baseUrl;
        }
        
        $this->baseUrl = $baseUrl;
        
        // Sanitizar API Key - remover apenas espaços extras
        $this->apiKey = trim($apiKey);
        
        // Nome da instância - apenas trim, manter espaços internos se houver
        $this->instanceName = trim($instanceName) ?: 'montaloja';
    }
    
    private function request(string $endpoint, string $method = 'GET', array $data = null): array {
        $url = $this->baseUrl . $endpoint;
        
        // Validar URL
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            return ['success' => false, 'error' => 'URL inválida: ' . $url, 'http_code' => 0];
        }
        
        $headers = [
            'Content-Type: application/json',
            'apikey: ' . $this->apiKey
        ];
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
            }
        } elseif ($method === 'PUT') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
            }
        } elseif ($method === 'DELETE') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
        }
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            return ['success' => false, 'error' => $error, 'http_code' => $httpCode];
        }
        
        $decoded = json_decode($response, true);
        return [
            'success' => $httpCode >= 200 && $httpCode < 300,
            'data' => $decoded,
            'http_code' => $httpCode,
            'raw_response' => $response
        ];
    }
    
    // ==================== INSTÂNCIA ====================
    
    public function createInstance(string $instanceName = null, array $options = []): array {
        $name = $instanceName ?? $this->instanceName;
        
        $payload = array_merge([
            'instanceName' => $name,
            'qrcode' => true,
            'integration' => 'WHATSAPP-BAILEYS'
        ], $options);
        
        return $this->request('/instance/create', 'POST', $payload);
    }
    
    public function connectInstance(string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        return $this->request('/instance/connect/' . rawurlencode($name), 'GET');
    }
    
    public function getConnectionState(string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        return $this->request('/instance/connectionState/' . rawurlencode($name), 'GET');
    }
    
    public function logoutInstance(string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        return $this->request('/instance/logout/' . rawurlencode($name), 'DELETE');
    }
    
    public function deleteInstance(string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        return $this->request('/instance/delete/' . rawurlencode($name), 'DELETE');
    }
    
    public function fetchInstances(): array {
        return $this->request('/instance/fetchInstances', 'GET');
    }
    
    // ==================== MENSAGENS ====================
    
    public function sendText(string $phone, string $message, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendText/' . rawurlencode($name), 'POST', [
            'number' => $phone,
            'text' => $message
        ]);
    }
    
    public function sendImage(string $phone, string $imageUrl, string $caption = '', string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendMedia/' . rawurlencode($name), 'POST', [
            'number' => $phone,
            'mediatype' => 'image',
            'media' => $imageUrl,
            'caption' => $caption
        ]);
    }
    
    public function sendDocument(string $phone, string $documentUrl, string $fileName, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendMedia/' . rawurlencode($name), 'POST', [
            'number' => $phone,
            'mediatype' => 'document',
            'media' => $documentUrl,
            'fileName' => $fileName
        ]);
    }
    
    public function sendAudio(string $phone, string $audioUrl, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendWhatsAppAudio/' . rawurlencode($name), 'POST', [
            'number' => $phone,
            'audio' => $audioUrl
        ]);
    }
    
    public function sendLocation(string $phone, float $latitude, float $longitude, string $locName = '', string $address = '', string $instanceName = null): array {
        $instance = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendLocation/' . rawurlencode($instance), 'POST', [
            'number' => $phone,
            'latitude' => $latitude,
            'longitude' => $longitude,
            'name' => $locName,
            'address' => $address
        ]);
    }
    
    public function sendButtons(string $phone, string $title, string $description, array $buttons, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendButtons/' . rawurlencode($name), 'POST', [
            'number' => $phone,
            'title' => $title,
            'description' => $description,
            'buttons' => $buttons
        ]);
    }
    
    public function sendList(string $phone, string $title, string $description, string $buttonText, array $sections, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/message/sendList/' . rawurlencode($name), 'POST', [
            'number' => $phone,
            'title' => $title,
            'description' => $description,
            'buttonText' => $buttonText,
            'sections' => $sections
        ]);
    }
    
    // ==================== CONTATOS ====================
    
    public function checkNumber(string $phone, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/chat/whatsappNumbers/' . rawurlencode($name), 'POST', [
            'numbers' => [$phone]
        ]);
    }
    
    public function getProfilePicture(string $phone, string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        $phone = $this->formatPhone($phone);
        
        return $this->request('/chat/fetchProfilePictureUrl/' . rawurlencode($name), 'POST', [
            'number' => $phone
        ]);
    }
    
    // ==================== WEBHOOK ====================
    
    public function setWebhook(string $webhookUrl, array $events = [], string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        
        $defaultEvents = [
            'QRCODE_UPDATED',
            'MESSAGES_UPSERT',
            'MESSAGES_UPDATE',
            'SEND_MESSAGE',
            'CONNECTION_UPDATE'
        ];
        
        return $this->request('/webhook/set/' . rawurlencode($name), 'POST', [
            'webhook' => [
                'enabled' => true,
                'url' => $webhookUrl,
                'webhookByEvents' => false,
                'events' => empty($events) ? $defaultEvents : $events
            ]
        ]);
    }
    
    public function getWebhook(string $instanceName = null): array {
        $name = $instanceName ?? $this->instanceName;
        return $this->request('/webhook/find/' . rawurlencode($name), 'GET');
    }
    
    // ==================== UTILITÁRIOS ====================
    
    private function formatPhone(string $phone): string {
        $phone = preg_replace('/\D/', '', $phone);
        
        if (strlen($phone) > 0 && substr($phone, 0, 2) !== '55') {
            $phone = '55' . $phone;
        }
        
        return $phone;
    }
    
    public function getInstanceName(): string {
        return $this->instanceName;
    }
    
    public function setInstanceName(string $instanceName): void {
        $this->instanceName = trim($instanceName) ?: 'montaloja';
    }
    
    public function getBaseUrl(): string {
        return $this->baseUrl;
    }
    
    public function testConnection(): array {
        return $this->fetchInstances();
    }
}
