<?php

namespace App\Services;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use RuntimeException;

/**
 * Thin Twitch Helix client. Replaces twitch-bot/search-game.py + set-channel.py
 * for use from `php artisan rig:loading`.
 *
 * Requires TWITCH_CLIENT_ID + TWITCH_ACCESS_TOKEN (user OAuth token with the
 * channel:manage:broadcast scope) and TWITCH_BROADCASTER_ID in .env.
 * Legacy TWITCH_TOKEN is still accepted as a fallback (see config/rig.php).
 */
class TwitchHelix
{
    private Client $http;
    private string $clientId;
    private string $token;
    private string $broadcasterId;

    public function __construct()
    {
        $this->clientId      = (string) config('rig.twitch.client_id');
        $this->token         = (string) config('rig.twitch.token');
        $this->broadcasterId = (string) config('rig.twitch.broadcaster_id');
        $this->http          = new Client([
            'base_uri' => 'https://api.twitch.tv/helix/',
            'timeout'  => 8.0,
        ]);
    }

    public function enabled(): bool
    {
        return $this->clientId !== '' && $this->token !== '';
    }

    /**
     * Returns [['id' => '12345', 'name' => 'Half-Life 2'], …] for an exact-name match,
     * or null if Twitch returned no matches.
     */
    public function searchCategory(string $query): ?array
    {
        try {
            $res = $this->http->get('search/categories', [
                'headers' => $this->headers(),
                'query'   => ['query' => $query, 'first' => 20],
            ]);
        } catch (GuzzleException $e) {
            throw new RuntimeException('Twitch search failed: ' . $e->getMessage(), 0, $e);
        }
        $body = json_decode((string) $res->getBody(), true);
        $hits = $body['data'] ?? [];
        if (empty($hits)) return null;

        // Prefer exact (case-insensitive) match; otherwise the first hit Twitch returned.
        foreach ($hits as $row) {
            if (strcasecmp((string) ($row['name'] ?? ''), $query) === 0) {
                return ['id' => (string) $row['id'], 'name' => (string) $row['name']];
            }
        }
        return ['id' => (string) $hits[0]['id'], 'name' => (string) $hits[0]['name']];
    }

    public function setChannel(string $title, ?string $gameId = null): void
    {
        if ($this->broadcasterId === '') {
            throw new RuntimeException('TWITCH_BROADCASTER_ID not set in .env');
        }
        $body = ['title' => $title];
        if ($gameId !== null && $gameId !== '') $body['game_id'] = $gameId;

        try {
            $this->http->patch('channels', [
                'headers' => $this->headers() + ['Content-Type' => 'application/json'],
                'query'   => ['broadcaster_id' => $this->broadcasterId],
                'json'    => $body,
            ]);
        } catch (GuzzleException $e) {
            throw new RuntimeException('Twitch PATCH /helix/channels failed: ' . $e->getMessage(), 0, $e);
        }
    }

    private function headers(): array
    {
        return [
            'Authorization' => 'Bearer ' . $this->token,
            'Client-Id'     => $this->clientId,
        ];
    }
}
