<?php

namespace Clonable\Traits;

use Clonable\Exceptions\ApiException;
use Clonable\Exceptions\CurlException;
use Clonable\Helpers\Session;
use Clonable\Services\ApiService;

/**
 * Class with common validation function used in Controllers
 */
trait Validation {
    /**
     * Automatically runs validation methods for all given fields.
     * It will take the id of the field and will add an _validate suffix.
     *
     * For example: For field "clonable_description" the function clonable_description_validate($input) will be ran.
     * @param $request
     * @param array $fields
     * @return void
     */
    public function validate_fields($request, $fields) {
        foreach ($fields as $id => $field) {
            $validation_method = $id . '_validate';
            if (is_callable([$this, $validation_method])) {
                $option_name = $field['setting'];
                $validation_response = $this->$validation_method($request[$option_name] ?? null);
                if ($validation_response === false) {
                    Session::put_validation_data($option_name, $request[$option_name]);
                } else {
                    update_option($option_name, $validation_response, true);
                }
            }
        }
    }

    /**
     * Validation method for common checkbox validation
     * @param $input string the value of the checkbox
     * @param $setting string WordPress option api value
     * @return string|null
     */
    public function validate_checkbox($input, $setting) {
        if (!$input) {
            return null;
        }

        if (gettype($input) !== 'string' && !($input === 'on' || $input === 'off')) {
            add_settings_error($setting, 'err_invalid_value', 'The supplied value was not valid for a checkbox.');
            return null;
        }

        return $input;
    }

    /**
     * Validation method for common color input validation.
     * Validates the input as hexadecimal string.
     * @param $input string the value of the checkbox
     * @param $setting string WordPress option api value
     * @return string|null
     */
    public function validate_color_input($input, $setting) {
        if (!$input) {
            return null;
        }

        if (!preg_match("/^#[a-fA-F0-9]{6}$/", $input)) {
            add_settings_error($setting, 'err_invalid_value', 'The supplied color was not in the correct format, reverting back to default.');
            return '#ffffff';
        }

        return $input;
    }

    /**
     * Validation method for common select input validation.
     * @param $input string the value of the checkbox
     * @param $valid_options string[] all possible valid values
     * @param $setting string WordPress option api value
     * @return string|null return the first value of the array when an invalid value is passed.
     */
    public function validate_select($input, $valid_options, $setting) {
        if (!$input || !$valid_options) {
            return null;
        }

        if (!in_array($input, $valid_options)) {
            add_settings_error($setting, 'err_invalid_value', 'The supplied value was not one of the options.');
            return $valid_options[array_key_first($valid_options)];
        }

        return $input;
    }

    public function validate_api_key($input, $setting) {
        if (!$input) {
            return null;
        }

        if (!preg_match("/^clonable_[a-z0-9]{8}_[a-z0-9]{24}$/", $input)) {
            add_settings_error($setting, 'err_invalid_value', 'The api key has the incorrect format, make sure you copy the key correctly from Clonable.');
            return null;
        }

        try {
            $api_response = ApiService::get_user($input);
        } catch (ApiException $e) {
            add_settings_error($setting, 'err_invalid_value', "Cannot validate the api key due to and error code {$e->getCode()} in the Clonable api, please contact Clonable support.");
            return null;
        } catch (CurlException $e) {
            add_settings_error($setting, 'err_invalid_value', "Cannot validate the api key due to an connection problem between your WordPress installation and Clonable: {$e->getMessage()}");
            return null;
        }

        if ($api_response->get_code() !== 200) {
            add_settings_error($setting, 'err_invalid_value', 'You seem to have given a invalid api key, make sure you copy the key correctly from Clonable.');
            return null;
        }

        return $input;
    }

	public function validate_email_strict($email): bool {
		if ($email === '') {
			return false;
		}

		// WP's is_email() may not be available in some contexts (e.g. static analysis / early load).
		if (function_exists('is_email')) {
			return is_email($email) !== false;
		} else {
			return filter_var($email ,FILTER_VALIDATE_EMAIL) !== false;
		}
	}
}