<?php

use Dedoc\Scramble\PhpDoc\PhpDocTypeHelper;
use Dedoc\Scramble\Support\PhpDoc;

function getPhpTypeFromDoc_Copy(string $phpDoc)
{
    $docNode = PhpDoc::parse($phpDoc);
    $varNode = $docNode->getVarTagValues()[0];

    return PhpDocTypeHelper::toType($varNode->type);
}

it('parses php doc into type correctly', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ['/** @var Foo */', 'Foo'],
    ['/** @var Foo<Bar, Baz> */', 'Foo<Bar, Baz>'],
]);

it('parses tuple', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ['/** @var array{float, float} */', 'list{float, float}'],
]);

it('parses class-string', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ['/** @var class-string<mixed> */', 'class-string<mixed>'],
]);

it('parses list', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ['/** @var list<float> */', 'array<float>'],
]);

it('parses integers', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ['/** @var int */', 'int'],
    ['/** @var integer */', 'int'],
    ['/** @var positive-int */', 'int<1, max>'],
    ['/** @var negative-int */', 'int<min, -1>'],
    ['/** @var non-positive-int */', 'int<min, 0>'],
    ['/** @var non-negative-int */', 'int<0, max>'],
    ['/** @var non-zero-int */', 'int'],
    ['/** @var int<10, 11> */', 'int<10, 11>'],
    ['/** @var int<10, max> */', 'int<10, max>'],
    ['/** @var int<min, 10> */', 'int<min, 10>'],
    ['/** @var int<max, 10> */', 'int'],
    ['/** @var int<10, min> */', 'int'],
]);

it('parses strings', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ['/** @var string */', 'string'],
    ['/** @var non-empty-string */', 'string'],
    ['/** @var callable-string */', 'string'],
    ['/** @var numeric-string */', 'string'],
    ['/** @var non-falsy-string */', 'string'],
    ['/** @var truthy-string */', 'string'],
    ['/** @var literal-string */', 'string'],
    ['/** @var lowercase-string */', 'string'],
    ['/** @var uppercase-string */', 'string'],
    ['/** @var non-empty-lowercase-string */', 'string'],
    ['/** @var non-empty-uppercase-string */', 'string'],
    ['/** @var non-empty-literal-string */', 'string'],
]);

it('parses unions', function (string $phpDocType, string $expectedTypeString) {
    expect(
        getPhpTypeFromDoc_Copy($phpDocType)->toString()
    )->toBe($expectedTypeString);
})->with([
    ["/** @var 'idle'|'charging'|'discharging'|null */", 'string(idle)|string(charging)|string(discharging)|null'],
]);
