<?php
/**
 * MercadoPagoAdapter
 * 
 * Implementação do PaymentGatewayInterface para MercadoPago.
 * Suporta Pix, Checkout Pro e consultas de status.
 * 
 * @package Payment
 */

namespace Payment;

class MercadoPagoAdapter implements PaymentGatewayInterface
{
    private string $accessToken;
    private string $publicKey;
    private string $environment;
    private string $baseUrl;
    
    // Métodos de pagamento suportados
    private array $supportedMethods = ['pix', 'credit_card', 'boleto', 'checkout'];

    /**
     * Construtor
     * 
     * @param string $accessToken Access Token do MercadoPago
     * @param string $publicKey Public Key (para frontend)
     * @param string $environment sandbox ou production
     */
    public function __construct(string $accessToken, string $publicKey = '', string $environment = 'sandbox')
    {
        $this->accessToken = $accessToken;
        $this->publicKey = $publicKey;
        $this->environment = $environment;
        $this->baseUrl = 'https://api.mercadopago.com';
    }

    /**
     * {@inheritdoc}
     */
    public function createTransaction(
        float $amount, 
        array $customerData, 
        array $items,
        string $paymentMethod = 'pix'
    ): array {
        
        if ($paymentMethod === 'pix') {
            return $this->createPixPayment($amount, $customerData, $items);
        }
        
        throw new \InvalidArgumentException("Método de pagamento '$paymentMethod' não implementado diretamente. Use createCheckoutSession para outros métodos.");
    }

    /**
     * Cria pagamento via Pix
     */
    private function createPixPayment(float $amount, array $customerData, array $items): array
    {
        $payload = [
            'transaction_amount' => $amount,
            'description' => $items[0]['title'] ?? 'Assinatura DuoLead',
            'payment_method_id' => 'pix',
            'payer' => [
                'email' => $customerData['email'],
                'first_name' => $customerData['first_name'] ?? '',
                'last_name' => $customerData['last_name'] ?? '',
                'identification' => [
                    'type' => $customerData['doc_type'] ?? 'CPF',
                    'number' => $customerData['doc_number'] ?? ''
                ]
            ]
        ];

        $response = $this->makeRequest('POST', '/v1/payments', $payload);

        if (isset($response['id'])) {
            return [
                'success' => true,
                'transaction_id' => $response['id'],
                'status' => $response['status'],
                'payment_method' => 'pix',
                'pix_qr_code' => $response['point_of_interaction']['transaction_data']['qr_code'] ?? null,
                'pix_qr_code_base64' => $response['point_of_interaction']['transaction_data']['qr_code_base64'] ?? null,
                'pix_copy_paste' => $response['point_of_interaction']['transaction_data']['qr_code'] ?? null,
                'expiration_date' => $response['date_of_expiration'] ?? null,
                'raw_response' => $response
            ];
        }

        return [
            'success' => false,
            'error' => $response['message'] ?? 'Erro ao criar pagamento Pix',
            'raw_response' => $response
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function createCheckoutSession(
        float $amount,
        array $customerData,
        array $items,
        string $successUrl,
        string $failureUrl
    ): array {
        
        $preferenceItems = [];
        foreach ($items as $item) {
            $preferenceItems[] = [
                'title' => $item['title'],
                'quantity' => $item['quantity'] ?? 1,
                'unit_price' => $item['unit_price'] ?? $amount,
                'currency_id' => 'BRL'
            ];
        }

        $payload = [
            'items' => $preferenceItems,
            'payer' => [
                'email' => $customerData['email'],
                'name' => $customerData['name'] ?? (($customerData['first_name'] ?? '') . ' ' . ($customerData['last_name'] ?? ''))
            ],
            'back_urls' => [
                'success' => $successUrl,
                'failure' => $failureUrl,
                'pending' => $successUrl . '?status=pending'
            ],
            'auto_return' => 'approved',
            'external_reference' => $customerData['external_reference'] ?? uniqid('ref_'),
            'notification_url' => $customerData['webhook_url'] ?? null
        ];

        $response = $this->makeRequest('POST', '/checkout/preferences', $payload);

        if (isset($response['id'])) {
            $checkoutUrl = $this->environment === 'production' 
                ? $response['init_point'] 
                : $response['sandbox_init_point'];

            return [
                'success' => true,
                'preference_id' => $response['id'],
                'checkout_url' => $checkoutUrl,
                'init_point' => $response['init_point'],
                'sandbox_init_point' => $response['sandbox_init_point'],
                'raw_response' => $response
            ];
        }

        return [
            'success' => false,
            'error' => $response['message'] ?? 'Erro ao criar preferência de checkout',
            'raw_response' => $response
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function getTransactionStatus(string $transactionId): array
    {
        $response = $this->makeRequest('GET', "/v1/payments/{$transactionId}");

        if (isset($response['id'])) {
            return [
                'success' => true,
                'transaction_id' => $response['id'],
                'status' => $response['status'],
                'status_detail' => $response['status_detail'] ?? null,
                'amount' => $response['transaction_amount'],
                'paid_at' => $response['date_approved'] ?? null,
                'payment_method' => $response['payment_method_id'],
                'raw_response' => $response
            ];
        }

        return [
            'success' => false,
            'error' => $response['message'] ?? 'Transação não encontrada',
            'raw_response' => $response
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function getSubscriptionStatus(string $subscriptionId): array
    {
        $response = $this->makeRequest('GET', "/preapproval/{$subscriptionId}");

        if (isset($response['id'])) {
            return [
                'success' => true,
                'subscription_id' => $response['id'],
                'status' => $response['status'],
                'payer_email' => $response['payer_email'] ?? null,
                'raw_response' => $response
            ];
        }

        return [
            'success' => false,
            'error' => $response['message'] ?? 'Assinatura não encontrada',
            'raw_response' => $response
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function cancelSubscription(string $subscriptionId): bool
    {
        $response = $this->makeRequest('PUT', "/preapproval/{$subscriptionId}", [
            'status' => 'cancelled'
        ]);

        return isset($response['id']) && $response['status'] === 'cancelled';
    }

    /**
     * {@inheritdoc}
     */
    public function processWebhook(array $payload, string $signature = ''): array
    {
        $type = $payload['type'] ?? null;
        $action = $payload['action'] ?? null;
        
        // Tipo de notificação IPN (Instant Payment Notification)
        if ($type === 'payment') {
            $paymentId = $payload['data']['id'] ?? null;
            if ($paymentId) {
                return $this->getTransactionStatus($paymentId);
            }
        }

        return [
            'success' => false,
            'error' => 'Tipo de webhook não suportado',
            'type' => $type,
            'action' => $action
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function getName(): string
    {
        return 'mercadopago';
    }

    /**
     * {@inheritdoc}
     */
    public function supportsPaymentMethod(string $method): bool
    {
        return in_array($method, $this->supportedMethods);
    }

    /**
     * Retorna a Public Key para uso no frontend
     */
    public function getPublicKey(): string
    {
        return $this->publicKey;
    }

    /**
     * Faz requisição para a API do MercadoPago
     */
    private function makeRequest(string $method, string $endpoint, array $data = []): array
    {
        $url = $this->baseUrl . $endpoint;
        
        $headers = [
            'Authorization: Bearer ' . $this->accessToken,
            'Content-Type: application/json',
            'X-Idempotency-Key: ' . uniqid()
        ];

        $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);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        } elseif ($method === 'PUT') {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            return [
                'success' => false,
                'error' => 'Erro de conexão: ' . $error,
                'http_code' => $httpCode
            ];
        }

        return json_decode($response, true) ?? ['error' => 'Resposta inválida'];
    }
}
