<?php

use auditLogs\constants\AuditLogSettingsNames;

/**
 * @uri /vcs/settings
 * @uri /dc/workspace/settings
 */
class VcsSettings extends CfProtectedResource
{
    public function __construct($parameters = array())
    {
        parent::__construct($parameters);


        $userSettings      = new stdClass();
        $this->vcsSettings = new VcsSettingsLib();

        $userSettings->username  = $this->username;
        $userSettings->gitServer = $this->vcsSettings->get_dc_staging_repository();
        $userSettings->gitBranch = $this->vcsSettings->get_dc_git_working_branch();
        $this->vcsApi            = new VcsApi($userSettings);
    }

    private function _validateParameters($data)
    {
        $validationError = array();
        $gitServer       = $data['gitServer'];
        $vcsType = $data['vcsType'];
        $gitRefspec  = $data['gitRefspec'];
        $projectSubdirectory  = $data['projectSubdirectory'] ?? '';

        if (empty($gitServer)) {
            $error          = new stdClass();
            $error->field   = 'gitServer';
            $error->message = 'Git server not set';
            array_push($validationError, $error);
        }

        if (!in_array($vcsType, VcsApi::VCS_TYPES)) {
            $error          = new stdClass();
            $error->field   = 'vcsType';
            $error->message = 'Wrong VCS type value. Allowed values: ' . implode(', ', VcsApi::VCS_TYPES);
            array_push($validationError, $error);
        }

        if (empty($gitRefspec)) {
            $error          = new stdClass();
            $error->field   = 'gitRefspec';
            $error->message = 'Git Refspec Type not set';
            array_push($validationError, $error);
        }

        if (!empty($projectSubdirectory) && str_starts_with($projectSubdirectory, '/')) {
            $error = new stdClass();
            $error->field = 'projectSubdirectory';
            $error->message = 'Project Subdirectory should not start with /';
            array_push($validationError, $error);
        }

        return empty($validationError) ? true : $validationError;
    }

    /**
     * @param $request
     *
     * @rbacName View VCS settings
     * @rbacGroup Version control system
     * @rbacAlias vcs.get
     *
     * @return Response
     */
    public function get($request)
    {
        $response    = new Response($request);
        $paramFile   = $this->vcsSettings->get_dc_params_file_path();
        if (@file_exists($paramFile)) {
            $data           = $this->vcsSettings->parseSettings($paramFile, $hideSensitiveData = true);
            $response->body = utils::packageResult($data, 1, 1);
            $response->code = Response::OK;
        } else {
            $data           = array(
                'message' => "No configuration found at path $paramFile"
            );
            $response->code = Response::NOTFOUND;
            $response->body = json_encode($data);
        }

        return $response;
    }

    /**
     * @param $request
     *
     * @rbacName Update VCS settings
     * @rbacGroup Version control system
     * @rbacAlias vcs.post
     *
     * @return Response
     * @throws ResponseException
     */
    public function post($request)
    {
        $response   = new Response($request);
        $data       = (array)Utils::getValidJsonData($request->data);
        if (!isset($data['vcsType'])) {
            $data['vcsType'] = VcsApi::GIT_TYPE;
        }
        $validation = $this->_validateParameters($data);
        if ($validation === true) {
            try {

                $gitPrivateKeyChanged = false;
                if (isset($data['gitPrivateKey']) && !empty($data['gitPrivateKey'])) {
                    $this->vcsApi->writePrivateKey($data['gitPrivateKey']);
                    $gitPrivateKeyChanged = true;
                }

                $this->vcsApi->generateUpdateScripts($data);
                $response->body = json_encode($data);
                $response->code = Response::OK;

                AuditLogService::register([
                    AuditLogFields::ACTOR => $this->username,
                    AuditLogFields::OBJECT_TYPE => AuditLogObjectTypes::SETTINGS,
                    AuditLogFields::ACTION => AuditLogActions::UPDATE,
                    AuditLogFields::OBJECT_NAME => AuditLogSettingsNames::VCS,
                    AuditLogFields::DETAILS => ['Updated git / VCS settings. Git private key changed: ' . boolToYesNo($gitPrivateKeyChanged)]
                ]);

            } catch (Exception $e) {
                $data           = $e->getMessage();
                $response->code = Response::INTERNALSERVERERROR;
                $response->body = json_encode($data);
            }
        } else {
            $response->code = Response::BADREQUEST;
            $messages       = array();
            foreach ($validation as $error) {
                $messages[] = $error->message;
            }
            $data           = implode("\n", $messages);
            $response->body = json_encode($data);
        }

        $response->body .= PHP_EOL;
        return $response;
    }

    /**
     * @param $request
     *
     * @rbacName Delete VCS settings
     * @rbacGroup Version control system
     * @rbacAlias vcs.delete
     *
     * @return Response
     */
    public function delete($request)
    {
        $response = new Response($request);
        $keyfile  = $this->vcsSettings->get_dc_user_ssh_key_directory($this->username) . DIRECTORY_SEPARATOR . $this->vcsSettings->get_dc_user_ssh_key_name();
        @unlink($keyfile);
        $scriptsPath = $this->vcsSettings->get_dc_update_script_path();
        Utils::delete_git_update_scripts($scriptsPath);
        $response->body = json_encode([]);
        $response->code = Response::NOCONTENT;

        AuditLogService::register([
            AuditLogFields::ACTOR => $this->username,
            AuditLogFields::OBJECT_TYPE => AuditLogObjectTypes::SETTINGS,
            AuditLogFields::ACTION => AuditLogActions::DELETE,
            AuditLogFields::OBJECT_NAME => AuditLogSettingsNames::VCS,
            AuditLogFields::DETAILS => ['VCS settings disabled.']
        ]);

        return $response;
    }
}
