<?php
/**
 * PaymentFactory
 * 
 * Factory que consulta o banco de dados, verifica qual gateway está ativo
 * e instancia a classe adaptadora correta.
 * 
 * @package Payment
 */

namespace Payment;

require_once __DIR__ . '/PaymentGatewayInterface.php';
require_once __DIR__ . '/MercadoPagoAdapter.php';

class PaymentFactory
{
    private \PDO $db;
    private ?array $activeGateway = null;

    /**
     * Construtor
     * 
     * @param \PDO $db Conexão com o banco de dados
     */
    public function __construct(\PDO $db)
    {
        $this->db = $db;
    }

    /**
     * Cria e retorna a instância do gateway de pagamento ativo
     * 
     * @return PaymentGatewayInterface
     * @throws \RuntimeException Se nenhum gateway estiver ativo
     */
    public function create(): PaymentGatewayInterface
    {
        $gateway = $this->getActiveGateway();

        if (!$gateway) {
            throw new \RuntimeException('Nenhum gateway de pagamento está ativo. Configure em Super Admin > Gateways.');
        }

        return $this->instantiateAdapter($gateway);
    }

    /**
     * Obtém informações do gateway ativo do banco de dados
     * 
     * @return array|null
     */
    public function getActiveGateway(): ?array
    {
        if ($this->activeGateway !== null) {
            return $this->activeGateway;
        }

        $stmt = $this->db->prepare("
            SELECT id, name, display_name, public_key, secret_key, 
                   webhook_secret, environment, settings 
            FROM payment_gateways 
            WHERE is_active = 1 
            LIMIT 1
        ");
        $stmt->execute();
        $gateway = $stmt->fetch(\PDO::FETCH_ASSOC);

        if ($gateway && isset($gateway['settings'])) {
            $gateway['settings'] = json_decode($gateway['settings'], true);
        }

        $this->activeGateway = $gateway ?: null;
        return $this->activeGateway;
    }

    /**
     * Obtém todos os gateways cadastrados
     * 
     * @return array
     */
    public function getAllGateways(): array
    {
        $stmt = $this->db->query("
            SELECT id, name, display_name, public_key, secret_key, 
                   webhook_secret, oauth_client_id, oauth_client_secret, oauth_redirect_uri, is_active, environment, settings,
                   created_at, updated_at
            FROM payment_gateways 
            ORDER BY display_name ASC
        ");
        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    /**
     * Ativa um gateway específico (desativa os outros automaticamente)
     * 
     * @param int $gatewayId ID do gateway a ativar
     * @return bool
     */
    public function activateGateway(int $gatewayId): bool
    {
        try {
            $this->db->beginTransaction();

            // Desativa todos os gateways
            $this->db->exec("UPDATE payment_gateways SET is_active = 0");

            // Ativa o gateway selecionado
            $stmt = $this->db->prepare("UPDATE payment_gateways SET is_active = 1 WHERE id = ?");
            $stmt->execute([$gatewayId]);

            $this->db->commit();
            $this->activeGateway = null; // Reset cache
            return true;
        } catch (\Exception $e) {
            $this->db->rollBack();
            return false;
        }
    }

    /**
     * Atualiza credenciais de um gateway
     * 
     * @param int $gatewayId ID do gateway
     * @param array $data Dados a atualizar
     * @return bool
     */
    public function updateGateway(int $gatewayId, array $data): bool
    {
        $allowedFields = ['public_key', 'secret_key', 'webhook_secret', 'environment', 'settings', 'oauth_client_id', 'oauth_client_secret', 'oauth_redirect_uri'];
        $updates = [];
        $values = [];

        foreach ($allowedFields as $field) {
            if (isset($data[$field])) {
                $updates[] = "$field = ?";
                $values[] = $field === 'settings' ? json_encode($data[$field]) : $data[$field];
            }
        }

        if (empty($updates)) {
            return false;
        }

        $values[] = $gatewayId;
        $sql = "UPDATE payment_gateways SET " . implode(', ', $updates) . " WHERE id = ?";
        
        $stmt = $this->db->prepare($sql);
        return $stmt->execute($values);
    }

    /**
     * Instancia o adaptador correto baseado no nome do gateway
     * 
     * @param array $gateway Dados do gateway
     * @return PaymentGatewayInterface
     * @throws \RuntimeException Se o adaptador não existir
     */
    private function instantiateAdapter(array $gateway): PaymentGatewayInterface
    {
        switch ($gateway['name']) {
            case 'mercadopago':
                return new MercadoPagoAdapter(
                    $gateway['secret_key'],
                    $gateway['public_key'] ?? '',
                    $gateway['environment']
                );

            case 'stripe':
                // Futuro: require_once e instanciar StripeAdapter
                throw new \RuntimeException('Adaptador Stripe ainda não implementado.');

            case 'asaas':
                // Futuro: require_once e instanciar AsaasAdapter
                throw new \RuntimeException('Adaptador Asaas ainda não implementado.');

            default:
                throw new \RuntimeException("Adaptador para gateway '{$gateway['name']}' não encontrado.");
        }
    }

    /**
     * Verifica se há um gateway ativo configurado
     * 
     * @return bool
     */
    public function hasActiveGateway(): bool
    {
        return $this->getActiveGateway() !== null;
    }

    /**
     * Retorna a public key do gateway ativo (para uso no frontend)
     * 
     * @return string|null
     */
    public function getActivePublicKey(): ?string
    {
        $gateway = $this->getActiveGateway();
        return $gateway['public_key'] ?? null;
    }
}
