<?php

use auditLogs\constants\AuditLogSettingsNames;

/**
 * @uri /settings
 */
class Settings extends CfProtectedResource
{
    private CfSettings $cfSettings;
    public function __construct($parameters)
    {
        parent::__construct($parameters);
        $this->cfSettings = CfSettings::getInstance();
    }
    /**
     * @param $request
     *
     * @rbacName View settings
     * @rbacGroup Settings
     * @rbacAlias settings.get
     * @rbacAllowedByDefault
     *
     * @return Response
     */
    public function get($request)
    {
        $user = $this->username;

        $response = new Response($request);
        $settings = cfapi_settings_get($user);
        $settings = SettingsHelper::removeLdapPassword($settings);
        $response->body = $settings;
        $response->code = Response::OK;

        return $response;
    }

    /**
     * @param $request
     *
     * @rbacName Update settings
     * @rbacGroup Settings
     * @rbacAlias settings.update
     *
     * @return Response
     * @throws Exception
     */
    public function post($request)
    {
        $user = $this->username;

        $currentSettings = (array) (json_decode(cfapi_settings_get($user))->data[0] ?? []);// transform current settings to array
        $newSettings = (array)json_decode($request->data); // transform request data settings to array
        SettingsValidator::validateCreateUpdateRequest($newSettings);

        // cfapi_settings_get doesn't return value if the value is false
        $currentSettings['rbacEnabled'] = $currentSettings['rbacEnabled'] ?? false;
        $currentSettings['enforce2FA'] = $currentSettings['enforce2FA'] ?? false;
        $changedSettings = array_diff_assoc($newSettings, $currentSettings);

        $response = new Response($request);
        if (cfapi_settings_post($user, $request->data)) {
            $response->code = Response::NOCONTENT;
            AuditLogService::register([
                AuditLogFields::ACTOR => $this->username,
                AuditLogFields::OBJECT_TYPE => AuditLogObjectTypes::SETTINGS,
                AuditLogFields::OBJECT_NAME => AuditLogSettingsNames::PREFERENCES,
                AuditLogFields::ACTION => AuditLogActions::UPDATE,
                AuditLogFields::DETAILS => ['Settings updated.' , ['changes' => $changedSettings]],
            ]);
        } else {
            $response->code = Response::INTERNALSERVERERROR;
        }

        return $response;
    }

    /**
     * @param $request
     *
     * @rbacName Update settings
     * @rbacGroup Settings
     * @rbacAlias settings.update
     *
     * @return Response
     * @throws Exception
     */
    public function patch($request)
    {
        $user = $this->username;
        $settings = json_decode(cfapi_settings_get($user));
        $currentSettings = (array)$settings->data[0];// transform current settings to array
        $newSettings = (array)json_decode($request->data); // transform request data settings to array
        SettingsValidator::validateCreateUpdateRequest($newSettings);

        // cfapi_settings_get doesn't return value if the value is false
        $currentSettings['rbacEnabled'] = $currentSettings['rbacEnabled'] ?? false;
        $currentSettings['enforce2FA'] = $currentSettings['enforce2FA'] ?? false;
        $changedSettings = array_diff_assoc($newSettings, $currentSettings);
        $settings = array_replace($currentSettings, $newSettings);
        SettingsHelper::removeUnAllowedSettings($settings);
        $data = json_encode($settings); //replace current settings with new


        $response = new Response($request);

        if (cfapi_settings_post($user, $data)) {
            // if 2FA was enforced, we need to reset fist login after 2FA enforced
            // as it might have outdated values from the previous settings states
            $isTwoFaEnforced = array_key_exists(SettingsHelper::ENFORCE_2FA, $newSettings) && $newSettings[SettingsHelper::ENFORCE_2FA] && !$currentSettings[SettingsHelper::ENFORCE_2FA];
            if ($isTwoFaEnforced) {
                (new CfUsers($user))->resetFirstLoginAfter2faEnforcedForAllUsers();
            }

            AuditLogService::register([
                AuditLogFields::ACTOR => $this->username,
                AuditLogFields::OBJECT_TYPE => AuditLogObjectTypes::SETTINGS,
                AuditLogFields::OBJECT_NAME => AuditLogSettingsNames::PREFERENCES,
                AuditLogFields::ACTION => AuditLogActions::UPDATE,
                AuditLogFields::DETAILS => ['Settings updated.' , ['changes' => $changedSettings]],
            ]);

            $response->code = Response::NOCONTENT;
        } else {
            $response->code = Response::INTERNALSERVERERROR;
        }

        return $response;
    }


}
