<?php

namespace Build\Models;

use Build\Exceptions\CfbsNotFoundException;
use Build\Exceptions\InvalidCfbsFormatException;

class ProjectModulesModel
{
    const CFBS_PROJECT_PATH = '/opt/cfengine/build/projects/%d/cfbs.json';

    public function list(int $projectId)
    {
        $cfbsPath = sprintf(self::CFBS_PROJECT_PATH, $projectId);

        if (!file_exists($cfbsPath)) {
            throw new CfbsNotFoundException('cfbs config file is not found.');
        }

        $cfbsConfig = json_decode(file_get_contents($cfbsPath), $associative = true);
        if (!isset($cfbsConfig['build'])) {
            throw new InvalidCfbsFormatException('Malformed CFBS config file.');
        }

        return array_map(function ($module) {
            $module['encodedName'] = base64_encode($module['name']);
            return $module;
        }, $cfbsConfig['build']);
    }

    public function markExternalModules(array &$modules, ModulesListModel $modulesListModel)
    {
        $modulesName = array_reduce($modules, function ($reducer, $module) {
            $reducer[] = $module['name'];
            return $reducer;
        }, []);

        if (empty($modulesName)) {
            return;
        }

        $internalModules = array_reduce($modulesListModel->getModulesByName($modulesName), function ($reducer, $module) {
            $reducer[$module['name']] = $module;
            return $reducer;
        }, []);

        $externalModules = array_diff($modulesName, array_keys($internalModules));
        foreach ($modules as $key => $module) {
            /**
             * mark a module as external one when:
             *   * is not presented in the canonical index
             *   * has url, then it's added by url
             *   * name starts with `./ then it's added as a local file
             */
            $modules[$key]['isExternal'] = (
                in_array($module['name'], $externalModules) ||
                isset($module['url']) ||
                str_starts_with($module['name'], './')
            );
            $modules[$key]['availableVersion'] = $internalModules[$module['name']]['version'] ?? null;
        }
    }
}
