<?php

declare(strict_types=1);

namespace App\Tests\Integration;

use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7\ServerRequest;
use Pkirillw\MaxBotApi\Webhook\WebhookHandler;
use PHPUnit\Framework\TestCase;

final class WebhookSecretTest extends TestCase
{
    private const SECRET = 'topsecret';

    public function testRejectsMissingSecretWith401(): void
    {
        $handler = $this->makeHandler();
        $request = new ServerRequest('POST', '/webhook', [], $this->messageCreatedBody());
        $response = $handler->handle($request);
        self::assertSame(401, $response->getStatusCode());
    }

    public function testRejectsWrongSecretWith401(): void
    {
        $handler = $this->makeHandler();
        $request = (new ServerRequest('POST', '/webhook', [], $this->messageCreatedBody()))
            ->withHeader('X-Max-Bot-Api-Secret', 'wrong');
        $response = $handler->handle($request);
        self::assertSame(401, $response->getStatusCode());
    }

    public function testAcceptsValidSecretAndInvokesUserlandHandler(): void
    {
        $handler = $this->makeHandler();
        $received = null;
        $handler->setHandler(static function (object $update) use (&$received): void {
            $received = $update;
        });

        $request = (new ServerRequest('POST', '/webhook', [], $this->messageCreatedBody()))
            ->withHeader('X-Max-Bot-Api-Secret', self::SECRET);
        $response = $handler->handle($request);

        self::assertSame(200, $response->getStatusCode());
        self::assertNotNull($received);
        self::assertSame('message_created', $received->getUpdateType()->value);
    }

    public function testReturns400OnEmptyBody(): void
    {
        $handler = $this->makeHandler();
        $request = (new ServerRequest('POST', '/webhook'))
            ->withHeader('X-Max-Bot-Api-Secret', self::SECRET);
        $response = $handler->handle($request);
        self::assertSame(400, $response->getStatusCode());
    }

    public function testReturns405OnGet(): void
    {
        $handler = $this->makeHandler();
        $request = (new ServerRequest('GET', '/webhook'))
            ->withHeader('X-Max-Bot-Api-Secret', self::SECRET);
        $response = $handler->handle($request);
        self::assertSame(405, $response->getStatusCode());
    }

    private function makeHandler(): WebhookHandler
    {
        return new WebhookHandler(new Psr17Factory(), secret: self::SECRET, keepRawUpdates: true);
    }

    private function messageCreatedBody(): string
    {
        return json_encode([
            'update_type' => 'message_created',
            'timestamp' => 1_700_000_000_000,
            'message' => [
                'body' => ['mid' => 'mid-1', 'seq' => 1, 'text' => '/help'],
                'recipient' => ['chat_id' => 100, 'chat_type' => 'dialog'],
                'sender' => ['user_id' => 200, 'name' => 'Tester'],
            ],
        ], JSON_THROW_ON_ERROR);
    }
}
