<?php

namespace Ignite\Core;

use Exception;
use Nwidart\Modules\Facades\Module;

final class Version
{
    /**
     * Private constructor.
     */
    private function __construct()
    {
        // Do nothing.
    }

    /**
     * The instance of the version class.
     *
     * @return static
     */
    public static function instance()
    {
        return new static();
    }

    /**
     * Get the version.
     *
     * @return string
     * @throws Exception
     */
    public function get()
    {
        try {
            return $this->viaComposer();
        } catch (Exception $exception) {
            return $this->viaModule();
        }
    }

    /**
     * The instance represented as a string.
     *
     * @return string
     * @throws Exception
     */
    public function __toString()
    {
        return $this->get();
    }

    /**
     * Get the version from the module.json file.
     *
     * @param string $module
     *
     * @return string
     * @throws Exception
     */
    private function viaModule($module = 'core')
    {
        $module = Module::find($module);
        $version = $module->get('version');

        if (! $version) {
            throw new Exception("Unable to find the module {$module}.");
        }

        return $version;
    }

    /**
     * Get the version from the composer lock file.
     *
     * @param string $core
     *
     * @return string
     * @throws Exception
     */
    private function viaComposer($core = 'ignite/core')
    {
        if (! file_exists($composerLockFile = base_path('composer.lock'))) {
            throw new Exception('Unable to find the composer.lock file.');
        }

        $composerLockJson = file_get_contents($composerLockFile);
        $composerLockData = json_decode($composerLockJson, true);
        $composerPackages = collect($composerLockData['packages']);
        $composerVersion = $composerPackages->filter(function ($package) use ($core) {
            return strtolower($package['name']) === $core;
        })->first()['version'];

        if (! $composerVersion) {
            throw new Exception("Unable to find package {$core}.");
        }

        if (strpos($composerVersion, '.') !== false) {
            return $composerVersion;
        }

        return $this->viaModule() . '-' . $composerVersion;
    }
}
