<?php

declare(strict_types=1);

namespace Aeon\Automation\Tests\Integration\Changelog;

use Aeon\Automation\Changelog\Manipulator;
use Aeon\Automation\Changelog\Source\MarkdownSource;
use Aeon\Automation\Changes\Change;
use Aeon\Automation\Changes\Changes;
use Aeon\Automation\Changes\ChangesSource;
use Aeon\Automation\Changes\Type;
use Aeon\Automation\Configuration;
use Aeon\Automation\Release;
use Aeon\Automation\Tests\Mother\Changes\ChangeMother;
use Aeon\Calendar\Gregorian\DateTime;
use Aeon\Calendar\Gregorian\Day;
use Monolog\Test\TestCase;
use Psr\Log\NullLogger;

final class ManipulatorTest extends TestCase
{
    public function test_add_new_changed_to_unreleased_release() : void
    {
        $factory = new Release\FormatterFactory(new Configuration(new NullLogger(), \getenv('AUTOMATION_ROOT_DIR'), []));
        $formatter = $factory->create('markdown', 'keepachangelog');

        $release = new Release('Unreleased', Day::fromString('2021-01-4'));
        $release->add(new Changes(
            new Change(
                new ChangesSource(
                    ChangesSource::TYPE_COMMIT,
                    'aae10af449f10def5edda9f617760daf9d52cb6a',
                    'https://github.com/aeon-php/calendar/commit/aae10af449f10def5edda9f617760daf9d52cb6a',
                    'Update CHANGELOG.md',
                    'Update CHANGELOG.md',
                    DateTime::fromString('2021-01-01'),
                    'norberttech',
                    'https://github.com/norberttech'
                ),
                Type::changed(),
                'Update CHANGELOG.md'
            )
        ));
        $release->add(new Changes(
            new Change(
                new ChangesSource(
                    ChangesSource::TYPE_PULL_REQUEST,
                    '88',
                    'https://github.com/aeon-php/calendar/pull/88',
                    'Year::fromString method',
                    'Year::fromString method',
                    DateTime::fromString('2021-01-01'),
                    'norberttech',
                    'https://github.com/norberttech'
                ),
                Type::fixed(),
                'Year::fromString method'
            )
        ));

        $markdown = $formatter->formatRelease($release);

        $release->add(new Changes(
            new Change(
                new ChangesSource(
                    ChangesSource::TYPE_PULL_REQUEST,
                    '89',
                    'https://github.com/aeon-php/calendar/pull/89',
                    'Added something very cool',
                    'Added something very cool',
                    DateTime::fromString('2021-01-01'),
                    'norberttech',
                    'https://github.com/norberttech'
                ),
                Type::added(),
                'Added something very cool'
            )
        ));

        $manipulator = new Manipulator();
        $releases = $manipulator->update(new MarkdownSource($markdown), $release);

        $this->assertSame(1, $releases->count());
        $this->assertSame(1, \count($releases->all()[0]->changed()));
        $this->assertSame(1, \count($releases->all()[0]->fixed()));
        $this->assertSame(1, \count($releases->all()[0]->added()));
        $this->assertSame('89', $releases->all()[0]->added()[0]->source()->id());
    }

    public function test_keep_original_order_of_changes() : void
    {
        $source = new MarkdownSource(
            $input = \file_get_contents(__DIR__ . '/fixtures/php-matcher-changelog.md')
        );

        $factory = new Release\FormatterFactory(new Configuration(new NullLogger(), \getenv('AUTOMATION_ROOT_DIR'), []));
        $formatter = $factory->create('markdown', 'keepachangelog');

        $this->assertSame($input, $formatter->formatReleases($source->releases()));
    }

    public function test_special_characters_in_markdown() : void
    {
        $source = new MarkdownSource(
            $input = <<<'MARKDOWN'
## [Unreleased] - 2021-01-02

### Added
- [#214](https://github.com/coduo/php-matcher/pull/214) - **include ArrayMatcher in OrMatcher to fix issues with `@null@||@array@` pattern** - [@mtomala](https://github.com/mtomala)

## Contributors

- @mtomala

Generated by [Automation](https://github.com/aeon-php/automation)
MARKDOWN
        );

        $factory = new Release\FormatterFactory(new Configuration(new NullLogger(), \getenv('AUTOMATION_ROOT_DIR'), []));
        $formatter = $factory->create('markdown', 'keepachangelog');

        $this->assertSame($input, $formatter->formatRelease($source->releases()->all()[0]));
    }

    public function test_not_changing_unreleased_date_when_nothing_was_changed_except_date() : void
    {
        $source = new MarkdownSource(
            $input = <<<'MARKDOWN'
## [Unreleased] - 2021-01-02

### Added
- [#214](https://github.com/coduo/php-matcher/pull/214) - **include ArrayMatcher in OrMatcher to fix issues with `@null@||@array@` pattern** - [@mtomala](https://github.com/mtomala)

## Contributors

- @mtomala

Generated by [Automation](https://github.com/aeon-php/automation)
MARKDOWN
        );

        $release = new Release('Unreleased', Day::fromString('2020-01-05'));
        $release->add(
            new Changes(ChangeMother::pullRequestAdded(214, 'include ArrayMatcher in OrMatcher to fix issues with `@null@||@array@` pattern', 'mtomala'))
        );

        $manipulator = new Manipulator();

        $factory = new Release\FormatterFactory(new Configuration(new NullLogger(), \getenv('AUTOMATION_ROOT_DIR'), []));
        $formatter = $factory->create('markdown', 'keepachangelog');

        $this->assertSame($input, $formatter->formatRelease($manipulator->update($source, $release)->get('unreleased')));
    }
}
