<?php

declare(strict_types=1);

namespace Tricks\PackageHelper;

use Composer\Script\Event;
use z4kn4fein\SemVer\SemverException;
use z4kn4fein\SemVer\Version;

final class Release
{
    public function __construct(
        public HelperContract $helper
    ) {
        //
    }

    public static function release(Event $event): void
    {
        $helper = new Helper();
        $arguments = $event->getArguments();
        if (isset($arguments[0]) === false) {
            Helper::fail('Please give one of the following target levels: patch, minor, major.');
        }
        $target = TargetLevel::tryFrom($arguments[0]);
        if ($target === null) {
            Helper::fail("Given level $arguments[0] is not valid. Please select one of: patch, minor, major.");
        }

        $result = (new self($helper))->handle($target);
        if (is_string($result)) {
            Helper::fail($result);
        }
    }

    public function handle(TargetLevel $target): true|string
    {
        $outdated = $this->helper->execute('git pull --quiet || echo \'outdated\'');
        if ($outdated !== null) {
            return 'Your branch is not up to date. Please run `git pull --tags` first.';
        }
        $dirty = $this->helper->execute('git diff --quiet || echo \'dirty\'');
        if ($dirty !== null) {
            return 'You have unstaged changes. Please commit or stash them';
        }
        $cached = $this->helper->execute('git diff --cached --quiet || echo \'cached\'');
        if ($cached !== null) {
            return 'You have staged changes. Please commit or stash them.';
        }

        $latestTag = $this->helper->trimmedResponse('git describe --tags --abbrev=0');
        $currentHash = $this->helper->trimmedResponse('git show-ref --head | head -n 1');
        $latestTagHash = $this->helper->trimmedResponse("git show-ref -s $latestTag");

        if ($currentHash === $latestTagHash) {
            return 'This commit already has a tag.'.PHP_EOL;
        }
        try {
            $version = Version::parse($latestTag);
            $newVersion = match ($target) {
                TargetLevel::PATCH => $version->getNextPatchVersion(),
                TargetLevel::MINOR => $version->getNextMinorVersion(),
                TargetLevel::MAJOR => $version->getNextMajorVersion(),
            };
        } catch (SemverException $e) {
            return $e->getMessage();
        }

        $this->helper->execute("git tag $newVersion");
        $this->helper->execute("git push origin main $newVersion");
        echo "\033[42m Alles super! 🚀 \n\033[0m";
        return true;
    }
}
