<?php
class InstagramTokenManager
{
    private $clientId = '3244671079077138';
    private $clientSecret = '57118e9e4b1acacc39375b95020c202f';
    private $redirectUri = null;

    public function __construct() {
        $this->redirectUri = APP_URL . '/api/instagram/callback';
    } 

     // Método para obtener el access token
    public function getAccessToken()
    {
        try {
            $tokenData = $this->getTokenFromDatabase();
            
            if (!$tokenData) {
                error_instagram("No se encontró token de Instagram en la base de datos");
                throw new Exception("No hay token de Instagram disponible");
            }
            
            if ($this->isTokenExpiringSoon($tokenData['expires_at'])) {
                error_instagram("Token de Instagram expirará pronto, renovando...");
                $newTokenData = $this->refreshAccessToken($tokenData['access_token']);
                $this->storeTokenInDatabase($newTokenData['access_token'], $newTokenData['expires_at']);
                error_instagram("Token de Instagram renovado correctamente");
                return $newTokenData['access_token'];
            }
            
            return $tokenData['access_token'];
        } catch (Exception $e) {
            error_instagram("Error al obtener token de Instagram: " . $e->getMessage());
            throw $e; // Re-lanzamos la excepción para manejarla en nivel superior
        }
    }

    // Métodos para obtener información de configuración
    public function getClientId()
    {
        return $this->clientId;
    }

    public function getClientSecret()
    {
        return $this->clientSecret;
    }

    public function getRedirectUri()
    {
        return $this->redirectUri;
    }

    // Obtiene el token más reciente de la base de datos
    private function getTokenFromDatabase()
    {
        $db = new db();
        $conn = $db->connect();
        $stmt = $conn->query("SELECT access_token, expires_at FROM ig_access_tokens ORDER BY id DESC LIMIT 1");
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    // Determina si el token expirará pronto (menos de 7 días)
    private function isTokenExpiringSoon($expiresAt)
    {
        $expirationDate = new DateTime($expiresAt);
        $now = new DateTime();
        $interval = $now->diff($expirationDate);
        $daysRemaining = $interval->days;
        
        error_instagram("Token de Instagram expira en {$daysRemaining} días");
        return $daysRemaining < 7; // Lo consideramos "por expirar" si faltan < 7 días
    }

    // Renueva el token de Instagram llamando a la API correspondiente
    private function refreshAccessToken($currentToken)
    {
        $url = "https://graph.instagram.com/refresh_access_token?" .
               "grant_type=ig_refresh_token&" .
               "access_token={$currentToken}";
        
        error_instagram("Solicitando renovación de token: " . $url);
        
        $response = file_get_contents($url);
        $data = json_decode($response, true);
        
        if (isset($data['access_token'])) {
            // Usar 60 días o el valor de expires_in si está disponible
            $expiresIn = isset($data['expires_in']) ? $data['expires_in'] : 5184000; // 60 días en segundos
            $expiresAt = (new DateTime())->modify('+' . $expiresIn . ' seconds')->format('Y-m-d H:i:s');
            
            error_instagram("Token renovado. Expira el: " . $expiresAt);
            
            return [
                'access_token' => $data['access_token'],
                'expires_at' => $expiresAt
            ];
        }
        
        error_instagram("Error al renovar token: " . $response);
        throw new Exception('Error al renovar token de Instagram');
    }

    // Almacena el token en la base de datos
    private function storeTokenInDatabase($accessToken, $expiresAt)
    {
        $db = new db();
        $conn = $db->connect();
        $stmt = $conn->prepare("INSERT INTO ig_access_tokens (access_token, expires_at) VALUES (:access_token, :expires_at)");
        $stmt->bindParam(':access_token', $accessToken);
        $stmt->bindParam(':expires_at', $expiresAt);
        
        if (!$stmt->execute()) {
            error_instagram("Error al guardar token en la base de datos: " . json_encode($stmt->errorInfo()));
            throw new Exception("Error al guardar token en la base de datos");
        }
        
        error_instagram("Token guardado correctamente en la base de datos");
    }
    
    // Método para almacenar un token nuevo (por ejemplo, al recibir un token de corta duración)
    public function storeNewToken($accessToken, $expiresInSeconds = 5184000)
    {
        $expiresAt = (new DateTime())->modify('+' . $expiresInSeconds . ' seconds')->format('Y-m-d H:i:s');
        $this->storeTokenInDatabase($accessToken, $expiresAt);
        return $accessToken;
    }
}