<?php declare(strict_types=1);

use PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer;
use PhpCsFixer\Fixer\Import\OrderedImportsFixer;
use PhpCsFixer\Fixer\LanguageConstruct\FunctionToConstantFixer;
use PhpCsFixer\Fixer\Operator\NewWithBracesFixer;
use PhpCsFixer\Fixer\Operator\NewWithParenthesesFixer;
use PhpCsFixer\Fixer\Operator\OperatorLinebreakFixer;
use PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer;
use PhpCsFixer\Fixer\Whitespace\NoExtraBlankLinesFixer;
use PhpCsFixer\Fixer\Whitespace\NoWhitespaceInBlankLineFixer;
use SlevomatCodingStandard\Sniffs\Attributes\AttributeAndTargetSpacingSniff;
use SlevomatCodingStandard\Sniffs\Classes\ClassConstantVisibilitySniff;
use SlevomatCodingStandard\Sniffs\ControlStructures\NewWithoutParenthesesSniff;
use SlevomatCodingStandard\Sniffs\Namespaces\AlphabeticallySortedUsesSniff;
use SlevomatCodingStandard\Sniffs\Namespaces\DisallowGroupUseSniff;
use SlevomatCodingStandard\Sniffs\Namespaces\MultipleUsesPerLineSniff;
use SlevomatCodingStandard\Sniffs\Namespaces\NamespaceSpacingSniff;
use SlevomatCodingStandard\Sniffs\Namespaces\ReferenceUsedNamesOnlySniff;
use SlevomatCodingStandard\Sniffs\Namespaces\UseSpacingSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\UnionTypeHintFormatSniff;
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
use Symplify\EasyCodingStandard\Config\ECSConfig;

return ECSConfig::configure()
    ->withPreparedSets(
        symplify: true,
        arrays: true,
        comments: true,
        docblocks: true,
        spaces: true,
        namespaces: true,
        controlStructures: true,
        strict: true,
        cleanCode: true
    )
    ->withPhpCsFixerSets(
        perCS: true,
        perCSRisky: true,
        php80MigrationRisky: true,
        php83Migration: true,
    )
    ->withRules([
        AlphabeticallySortedUsesSniff::class,
        DisallowGroupUseSniff::class,
        MultipleUsesPerLineSniff::class,
        NamespaceSpacingSniff::class,
        OperatorLinebreakFixer::class,
        NoWhitespaceInBlankLineFixer::class,
        NewWithoutParenthesesSniff::class,
    ])
    ->withConfiguredRule(ClassConstantVisibilitySniff::class, [
        'fixable' => true,
    ])
    ->withConfiguredRule(
        ReferenceUsedNamesOnlySniff::class,
        [
            'allowFallbackGlobalConstants' => false,
            'allowFallbackGlobalFunctions' => false,
            'allowFullyQualifiedGlobalClasses' => false,
            'allowFullyQualifiedGlobalConstants' => false,
            'allowFullyQualifiedGlobalFunctions' => false,
            'allowFullyQualifiedNameForCollidingClasses' => true,
            'allowFullyQualifiedNameForCollidingConstants' => true,
            'allowFullyQualifiedNameForCollidingFunctions' => true,
            'searchAnnotations' => true,
        ]
    )

    // define newlines between use statements
    ->withConfiguredRule(
        UseSpacingSniff::class,
        [
            'linesCountAfterLastUse' => 1,
            'linesCountBeforeFirstUse' => 1,
            'linesCountBetweenUseTypes' => 1,
        ]
    )
    ->withConfiguredRule(
        ClassAttributesSeparationFixer::class,
        [
            'elements' => [
                'const' => 'none',
                'method' => 'one',
                'property' => 'none',
                'trait_import' => 'none',
                'case' => 'none',
            ],
        ],
    )->withConfiguredRule(
        DeclareStrictTypesSniff::class,
        [
            'declareOnFirstLine' => true,
            'spacesCountAroundEqualsSign' => 0,
        ]
    )
    ->withConfiguredRule(
        UnionTypeHintFormatSniff::class,
        [
            'nullPosition' => 'last',
            'shortNullable' => 'no',
            'withSpaces' => 'no',
        ]
    )
    ->withConfiguredRule(
        NoExtraBlankLinesFixer::class,
        [
            'tokens' => ['square_brace_block', 'return', 'extra'],
        ]
    )
    ->withConfiguredRule(AttributeAndTargetSpacingSniff::class, [
        'linesCount' => 0,
    ])
    ->withSkip([
        BlankLineAfterOpeningTagFixer::class,
        OrderedImportsFixer::class,
        FunctionToConstantFixer::class,
        NewWithParenthesesFixer::class,
        NewWithBracesFixer::class,
        LineLengthFixer::class,
    ]);