<?php
/**
 * Cliente liviano para Google Drive y Google Sheets (sin dependencias externas).
 * Usa solo file_get_contents + stream_context — sin Composer.
 */
class GoogleClient
{
    private string $tokenFile;
    private array  $token = [];

    public function __construct(string $tokenFile)
    {
        $this->tokenFile = $tokenFile;
        if (file_exists($tokenFile)) {
            $this->token = json_decode(file_get_contents($tokenFile), true) ?? [];
        }
    }

    // ─── Auth ──────────────────────────────────────────────────────────────

    private function accessToken(): string
    {
        if (empty($this->token['access_token'])) {
            throw new RuntimeException('Google no conectado. Visita /coarca/api/google-auth.php');
        }
        // Refresh si está próximo a expirar (margen 5 min)
        $createdAt = $this->token['created_at'] ?? 0;
        $expiresIn = $this->token['expires_in'] ?? 3600;
        if (time() > $createdAt + $expiresIn - 300) {
            $this->refreshToken();
        }
        return $this->token['access_token'];
    }

    private function refreshToken(): void
    {
        if (empty($this->token['refresh_token'])) {
            throw new RuntimeException('No hay refresh_token. Reconecta la cuenta Google.');
        }
        $data = http_build_query([
            'client_id'     => GOOGLE_CLIENT_ID,
            'client_secret' => GOOGLE_CLIENT_SECRET,
            'refresh_token' => $this->token['refresh_token'],
            'grant_type'    => 'refresh_token',
        ]);
        // httpRaw: sin Authorization header para evitar loop infinito
        $ctx = stream_context_create(['http' => [
            'method'        => 'POST',
            'header'        => "Content-Type: application/x-www-form-urlencoded\r\n",
            'content'       => $data,
            'ignore_errors' => true,
        ]]);
        $res = json_decode(file_get_contents('https://oauth2.googleapis.com/token', false, $ctx), true) ?? [];
        if (empty($res['access_token'])) {
            throw new RuntimeException('Refresh token fallido: ' . json_encode($res));
        }
        $this->token['access_token'] = $res['access_token'];
        $this->token['expires_in']   = $res['expires_in'];
        $this->token['created_at']   = time();
        file_put_contents($this->tokenFile, json_encode($this->token, JSON_PRETTY_PRINT));
    }

    // ─── Google Drive ──────────────────────────────────────────────────────

    /**
     * Obtiene o crea una carpeta en Drive dentro de $parentId.
     */
    public function getOrCreateFolder(string $name, string $parentId): string
    {
        // Buscar carpeta existente
        $q   = urlencode("mimeType='application/vnd.google-apps.folder' and name='" . addslashes($name) . "' and '" . $parentId . "' in parents and trashed=false");
        $res = $this->http('GET', "https://www.googleapis.com/drive/v3/files?q={$q}&fields=files(id,name)");
        if (!empty($res['files'][0]['id'])) {
            return $res['files'][0]['id'];
        }
        // Crear
        $res = $this->http('POST', 'https://www.googleapis.com/drive/v3/files', [], json_encode([
            'name'     => $name,
            'mimeType' => 'application/vnd.google-apps.folder',
            'parents'  => [$parentId],
        ]));
        return $res['id'];
    }

    /**
     * Sube un archivo a Drive y devuelve el fileId y webViewLink.
     */
    public function uploadFile(string $localPath, string $fileName, string $mimeType, string $folderId): array
    {
        $metadata  = json_encode(['name' => $fileName, 'parents' => [$folderId]]);
        $fileBytes = file_get_contents($localPath);
        $boundary  = 'boundary_' . bin2hex(random_bytes(8));

        $body  = "--{$boundary}\r\n";
        $body .= "Content-Type: application/json; charset=UTF-8\r\n\r\n";
        $body .= $metadata . "\r\n";
        $body .= "--{$boundary}\r\n";
        $body .= "Content-Type: {$mimeType}\r\n\r\n";
        $body .= $fileBytes . "\r\n";
        $body .= "--{$boundary}--";

        $res = $this->http(
            'POST',
            'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,webViewLink',
            [],
            $body,
            "multipart/related; boundary={$boundary}"
        );
        return $res;
    }

    // ─── Google Sheets ─────────────────────────────────────────────────────

    /**
     * Agrega una fila al final de la hoja.
     * $values es un array plano de valores en orden de columnas.
     */
    public function appendRow(string $spreadsheetId, string $range, array $values): void
    {
        $body = json_encode(['values' => [$values]]);
        $url  = "https://sheets.googleapis.com/v4/spreadsheets/{$spreadsheetId}/values/" . urlencode($range) . ":append?valueInputOption=USER_ENTERED&insertDataOption=INSERT_ROWS";
        $this->http('POST', $url, [], $body);
    }

    // ─── HTTP helper ───────────────────────────────────────────────────────

    private function http(string $method, string $url, array $extraHeaders = [], string $body = '', string $contentType = 'application/json'): array
    {
        $headers = ["Authorization: Bearer " . $this->accessToken()];
        if ($body !== '') {
            $headers[] = "Content-Type: {$contentType}";
        }
        foreach ($extraHeaders as $h) $headers[] = $h;

        $opts = [
            'http' => [
                'method'        => $method,
                'header'        => implode("\r\n", $headers),
                'content'       => $body,
                'ignore_errors' => true,
            ]
        ];
        $res = file_get_contents($url, false, stream_context_create($opts));
        $arr = json_decode($res, true) ?? [];
        if (!empty($arr['error'])) {
            throw new RuntimeException('Google API error: ' . json_encode($arr['error']));
        }
        return $arr;
    }
}
