<?php

declare(strict_types=1);

namespace App\Tests\Unit;

use App\Keyboard\KeyboardFactory;
use Pkirillw\MaxBotApi\Scheme\Button\CallbackButton;
use Pkirillw\MaxBotApi\Scheme\Button\ClipboardButton;
use Pkirillw\MaxBotApi\Scheme\Button\LinkButton;
use Pkirillw\MaxBotApi\Scheme\Button\MessageButton;
use Pkirillw\MaxBotApi\Scheme\Button\OpenAppButton;
use Pkirillw\MaxBotApi\Scheme\Button\RequestContactButton;
use Pkirillw\MaxBotApi\Scheme\Button\RequestGeoLocationButton;
use Pkirillw\MaxBotApi\Scheme\Enum\Intent;
use PHPUnit\Framework\TestCase;

final class KeyboardFactoryTest extends TestCase
{
    public function testFullKeyboardCoversAllButtonTypes(): void
    {
        $kb = (new KeyboardFactory('https://app.example.com/web'))->full();
        $rows = $kb->getRows();
        self::assertCount(7, $rows, 'full keyboard has 7 rows when WEB_APP_URL is set');

        // Flatten buttons.
        $buttons = [];
        foreach ($rows as $row) {
            foreach ($row->getButtons() as $button) {
                $buttons[] = $button;
            }
        }

        $types = array_map(fn($b) => $b->getType()->value, $buttons);
        self::assertContains('callback', $types);
        self::assertContains('link', $types);
        self::assertContains('message', $types);
        self::assertContains('clipboard', $types);
        self::assertContains('request_contact', $types);
        self::assertContains('request_geo_location', $types);
        self::assertContains('open_app', $types);
    }

    public function testFullKeyboardSkipsOpenAppWhenUrlMissing(): void
    {
        $kb = (new KeyboardFactory(null))->full();
        $rows = $kb->getRows();
        self::assertCount(6, $rows, 'OpenApp row is skipped without WEB_APP_URL');

        $buttons = [];
        foreach ($rows as $row) {
            foreach ($row->getButtons() as $button) {
                $buttons[] = $button;
            }
        }
        $types = array_map(fn($b) => $b->getType()->value, $buttons);
        self::assertNotContains('open_app', $types);
    }

    public function testCallbackRowCoversAllIntents(): void
    {
        $kb = (new KeyboardFactory())->full();
        $callbackRow = $kb->getRows()[0];
        $buttons = $callbackRow->getButtons();

        self::assertCount(3, $buttons);
        self::assertInstanceOf(CallbackButton::class, $buttons[0]);
        self::assertSame(Intent::Positive->value, $buttons[0]->intent->value);
        self::assertSame(Intent::Negative->value, $buttons[1]->intent->value);
        self::assertSame(Intent::Default->value, $buttons[2]->intent->value);
    }

    public function testJsonSerializationShape(): void
    {
        $kb = (new KeyboardFactory())->simpleCallback();
        $rows = $kb->getRows();

        self::assertCount(1, $rows);
        $buttons = $rows[0]->getButtons();
        self::assertCount(2, $buttons);

        $first = $buttons[0];
        self::assertInstanceOf(CallbackButton::class, $first);
        self::assertSame('vote:yes', $first->payload);

        $json = $kb->build()->jsonSerialize();
        self::assertArrayHasKey('buttons', $json);
        self::assertCount(1, $json['buttons']);
        // Each row serializes as a list of {type, text, ...} objects.
        self::assertSame('vote:yes', $json['buttons'][0][0]['payload']);
        self::assertSame('vote:no', $json['buttons'][0][1]['payload']);
    }
}
