<?php
namespace Avision;

/**
 * Intégration Google My Business API
 * 
 * Gère la communication avec l'API Google My Business
 * pour publier les réponses aux avis automatiquement.
 */
class Google_My_Business_API {
    
    private $access_token;
    private $location_id;
    private $api_base_url = 'https://mybusiness.googleapis.com/v4';
    
    /**
     * Constructeur
     * 
     * @param string $access_token Token OAuth 2.0
     * @param string $location_id ID de la fiche Google Business
     */
    public function __construct($access_token, $location_id) {
        $this->access_token = $access_token;
        $this->location_id = $location_id;
    }
    
    /**
     * Répond à un avis Google
     * 
     * @param string $review_id ID de l'avis Google
     * @param string $response_text Texte de la réponse
     * @return bool Succès de la publication
     */
    public function reply_to_review($review_id, $response_text) {
        $url = "{$this->api_base_url}/{$this->location_id}/reviews/{$review_id}/reply";
        
        $data = [
            'comment' => $response_text
        ];
        
        $response = $this->make_request('PUT', $url, $data);
        
        if ($response && isset($response['comment'])) {
            return true;
        }
        
        error_log('Google API Error: ' . print_r($response, true));
        return false;
    }
    
    /**
     * Récupère la liste des avis
     * 
     * @param int $page_size Nombre d'avis à récupérer
     * @return array Liste des avis
     */
    public function get_reviews($page_size = 50) {
        $url = "{$this->api_base_url}/{$this->location_id}/reviews?pageSize={$page_size}";
        
        $response = $this->make_request('GET', $url);
        
        if ($response && isset($response['reviews'])) {
            return $response['reviews'];
        }
        
        return [];
    }
    
    /**
     * Récupère un avis spécifique
     * 
     * @param string $review_id ID de l'avis
     * @return array|null Données de l'avis
     */
    public function get_review($review_id) {
        $url = "{$this->api_base_url}/{$this->location_id}/reviews/{$review_id}";
        
        return $this->make_request('GET', $url);
    }
    
    /**
     * Supprime une réponse à un avis
     * 
     * @param string $review_id ID de l'avis
     * @return bool Succès de la suppression
     */
    public function delete_reply($review_id) {
        $url = "{$this->api_base_url}/{$this->location_id}/reviews/{$review_id}/reply";
        
        $response = $this->make_request('DELETE', $url);
        
        return $response !== false;
    }
    
    /**
     * Vérifie si le token est valide
     * 
     * @return bool Token valide
     */
    public function verify_token() {
        $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' . $this->access_token;
        
        $response = $this->make_request('GET', $url);
        
        return $response && isset($response['expires_in']) && $response['expires_in'] > 0;
    }
    
    /**
     * Récupère les informations de la fiche
     * 
     * @return array|null Informations de la fiche
     */
    public function get_location_info() {
        $url = "{$this->api_base_url}/{$this->location_id}";
        
        return $this->make_request('GET', $url);
    }
    
    /**
     * Effectue une requête HTTP vers l'API Google
     * 
     * @param string $method Méthode HTTP (GET, POST, PUT, DELETE)
     * @param string $url URL de l'endpoint
     * @param array $data Données à envoyer (pour POST/PUT)
     * @return array|false Réponse de l'API ou false en cas d'erreur
     */
    private function make_request($method, $url, $data = null) {
        $headers = [
            'Authorization: Bearer ' . $this->access_token,
            'Content-Type: application/json'
        ];
        
        $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_CUSTOMREQUEST, $method);
        
        if ($data && in_array($method, ['POST', 'PUT'])) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
        
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        
        curl_close($ch);
        
        if ($error) {
            error_log('Google API cURL Error: ' . $error);
            return false;
        }
        
        if ($http_code >= 400) {
            error_log('Google API HTTP Error ' . $http_code . ': ' . $response);
            return false;
        }
        
        return json_decode($response, true);
    }
    
    /**
     * Configure le webhook pour recevoir les notifications d'avis
     * 
     * @param string $webhook_url URL du webhook
     * @return bool Succès de la configuration
     */
    public function setup_webhook($webhook_url) {
        // Note: Google My Business API ne supporte pas directement les webhooks
        // Il faut utiliser Pub/Sub de Google Cloud Platform
        
        $url = 'https://mybusiness.googleapis.com/v4/accounts/' . 
               $this->get_account_id() . '/notifications';
        
        $data = [
            'topicName' => 'projects/YOUR_PROJECT_ID/topics/reviews',
            'notificationTypes' => ['NEW_REVIEW', 'UPDATED_REVIEW']
        ];
        
        $response = $this->make_request('POST', $url, $data);
        
        return $response !== false;
    }
    
    /**
     * Extrait l'ID du compte depuis le location_id
     * 
     * @return string Account ID
     */
    private function get_account_id() {
        // Format: accounts/{accountId}/locations/{locationId}
        preg_match('/accounts\/([^\/]+)/', $this->location_id, $matches);
        return $matches[1] ?? '';
    }
    
    /**
     * Rafraîchit le token d'accès
     * 
     * @param string $refresh_token Token de rafraîchissement
     * @param string $client_id Client ID OAuth
     * @param string $client_secret Client Secret OAuth
     * @return string|false Nouveau token ou false
     */
    public static function refresh_access_token($refresh_token, $client_id, $client_secret) {
        $url = 'https://oauth2.googleapis.com/token';
        
        $data = [
            'client_id' => $client_id,
            'client_secret' => $client_secret,
            'refresh_token' => $refresh_token,
            'grant_type' => 'refresh_token'
        ];
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        
        $response = curl_exec($ch);
        curl_close($ch);
        
        $result = json_decode($response, true);
        
        if (isset($result['access_token'])) {
            return $result['access_token'];
        }
        
        return false;
    }
    
    // ══════════════════════════════════════════════
    // Médias (Photos / Vidéos)
    // ══════════════════════════════════════════════

    /**
     * Récupère la liste des médias (photos/vidéos) de la fiche.
     *
     * @param int $page_size Nombre max de médias
     * @return array Liste des mediaItems
     */
    public function get_media_items($page_size = 50) {
        $url = "{$this->api_base_url}/{$this->location_id}/media?pageSize={$page_size}";

        $response = $this->make_request('GET', $url);

        if ($response && isset($response['mediaItems'])) {
            return $response['mediaItems'];
        }

        return [];
    }

    /**
     * Récupère les photos de clients (CUSTOMERS) uniquement.
     *
     * @param int $page_size
     * @return array Photos clients
     */
    public function get_customer_photos($page_size = 50) {
        $all   = $this->get_media_items($page_size);
        $owner = [];

        foreach ($all as $item) {
            $attribution = $item['attribution']['profilePhotoUrl'] ?? null;
            $source      = $item['sourceUrl'] ?? '';
            $location    = $item['locationAssociation']['category'] ?? '';

            if ($location === 'CUSTOMERS' || (!empty($attribution) && $location !== 'PROFILE' && $location !== 'COVER')) {
                $owner[] = $item;
            }
        }

        return $owner;
    }

    /**
     * Publie un média (photo) sur la fiche Google.
     *
     * @param string $source_url  URL publique de l'image
     * @param string $category    COVER, PROFILE, ADDITIONAL, etc.
     * @param string $description Description de la photo
     * @return array|false Réponse API ou false
     */
    public function create_media_item($source_url, $category = 'ADDITIONAL', $description = '') {
        $url = "{$this->api_base_url}/{$this->location_id}/media";

        $data = [
            'mediaFormat'    => 'PHOTO',
            'sourceUrl'      => $source_url,
            'locationAssociation' => [
                'category' => $category,
            ],
        ];

        if ($description !== '') {
            $data['description'] = $description;
        }

        return $this->make_request('POST', $url, $data);
    }

    /**
     * Supprime un média de la fiche.
     *
     * @param string $media_name Nom complet du média (accounts/.../locations/.../media/...)
     * @return bool
     */
    public function delete_media_item($media_name) {
        $url = "{$this->api_base_url}/{$media_name}";

        $response = $this->make_request('DELETE', $url);

        return $response !== false;
    }

    // ══════════════════════════════════════════════
    // Local Posts (Actualités, Offres, Événements)
    // ══════════════════════════════════════════════

    /**
     * Récupère les posts locaux de la fiche.
     *
     * @param int $page_size
     * @return array Liste des localPosts
     */
    public function get_local_posts($page_size = 10) {
        $url = "{$this->api_base_url}/{$this->location_id}/localPosts?pageSize={$page_size}";

        $response = $this->make_request('GET', $url);

        if ($response && isset($response['localPosts'])) {
            return $response['localPosts'];
        }

        return [];
    }

    /**
     * Crée un post local (Actualité, Offre, Événement).
     *
     * @param string $summary   Texte du post (max 1500 chars)
     * @param string $topic     STANDARD, EVENT, OFFER
     * @param array  $media     ['sourceUrl' => '...', 'mediaFormat' => 'PHOTO'] (optionnel)
     * @param array  $call_to_action ['actionType' => 'LEARN_MORE', 'url' => '...'] (optionnel)
     * @return array|false
     */
    public function create_local_post($summary, $topic = 'STANDARD', $media = [], $call_to_action = []) {
        $url = "{$this->api_base_url}/{$this->location_id}/localPosts";

        $data = [
            'topicType'   => $topic,
            'summary'     => mb_substr($summary, 0, 1500),
            'languageCode' => 'fr',
        ];

        if (!empty($media)) {
            $data['media'] = [$media];
        }

        if (!empty($call_to_action)) {
            $data['callToAction'] = $call_to_action;
        }

        return $this->make_request('POST', $url, $data);
    }

    // ══════════════════════════════════════════════
    // Conversion / Helpers
    // ══════════════════════════════════════════════

    /**
     * Convertit un avis Google au format AVI
     * 
     * @param array $google_review Avis depuis l'API Google
     * @return array Avis au format AVI
     */
    public static function convert_google_review_to_avi_format($google_review) {
        return [
            'review_id' => $google_review['reviewId'] ?? '',
            'reviewer_name' => $google_review['reviewer']['displayName'] ?? 'Anonymous',
            'rating' => self::convert_star_rating($google_review['starRating'] ?? 'FIVE'),
            'text' => $google_review['comment'] ?? '',
            'created_at' => $google_review['createTime'] ?? date('Y-m-d H:i:s'),
            'language' => self::detect_language_from_google($google_review)
        ];
    }
    
    /**
     * Convertit le format d'étoiles Google en nombre
     * 
     * @param string $star_rating Format Google (ONE, TWO, THREE, FOUR, FIVE)
     * @return int Nombre d'étoiles (1-5)
     */
    private static function convert_star_rating($star_rating) {
        $mapping = [
            'ONE' => 1,
            'TWO' => 2,
            'THREE' => 3,
            'FOUR' => 4,
            'FIVE' => 5
        ];
        
        return $mapping[$star_rating] ?? 5;
    }
    
    /**
     * Détecte la langue depuis les données Google
     * 
     * @param array $google_review Avis Google
     * @return string Code langue (fr, en, etc.)
     */
    private static function detect_language_from_google($google_review) {
        // Google peut fournir la langue dans certains cas
        if (isset($google_review['reviewReply']['comment'])) {
            // Utiliser l'analyseur NLP pour détecter
            require_once __DIR__ . '/class-guardian-nlp-analyzer.php';
            $analyzer = new Guardian_NLP_Analyzer();
            return $analyzer->detect_language($google_review['comment'] ?? '');
        }
        
        return 'fr'; // Par défaut
    }
}
