<?php
/**
 * Credential encryption, masking, and constant/env resolution.
 *
 * @package EmailSmtp
 * @since 1.1.0
 */

namespace EmailSmtp\Includes;

use EmailSmtp\Module;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

final class CredentialManager {

	public const MASK = '••••••••••••';

	public const CIPHER_DOMAIN = 'wp_powersuite_smtp_key_v1';

	/**
	 * Priority: constant → environment → stored setting.
	 *
	 * @param array<string, mixed> $settings Full module settings.
	 * @param string               $setting_key Key inside settings / provider bag.
	 * @param string               $constant_name Optional WP constant name.
	 * @param string               $env_name Optional environment variable name.
	 */
	public static function resolve( array $settings, string $setting_key, string $constant_name = '', string $env_name = '' ): string {
		if ( $constant_name !== '' && defined( $constant_name ) ) {
			$value = constant( $constant_name );
			if ( is_scalar( $value ) && (string) $value !== '' ) {
				return (string) $value;
			}
		}

		if ( $env_name !== '' ) {
			$env = getenv( $env_name );
			if ( is_string( $env ) && $env !== '' ) {
				return $env;
			}
		}

		$stored = $settings[ $setting_key ] ?? '';
		if ( ! is_string( $stored ) || $stored === '' ) {
			return '';
		}

		if ( self::is_encrypted( $stored ) ) {
			self::ensure_module_loaded();
			return Module::decryptPasswordStatic( $stored );
		}

		return $stored;
	}

	public static function is_from_constant( string $constant_name ): bool {
		return $constant_name !== '' && defined( $constant_name ) && (string) constant( $constant_name ) !== '';
	}

	public static function is_from_env( string $env_name ): bool {
		if ( $env_name === '' ) {
			return false;
		}
		$env = getenv( $env_name );
		return is_string( $env ) && $env !== '';
	}

	public static function encrypt( string $plain ): string {
		self::ensure_module_loaded();
		return Module::encryptPassword( $plain );
	}

	public static function decrypt( string $stored ): string {
		self::ensure_module_loaded();
		return Module::decryptPasswordStatic( $stored );
	}

	public static function is_encrypted( string $value ): bool {
		return str_starts_with( $value, 'ENC2:' ) || str_starts_with( $value, 'ENC:' );
	}

	public static function is_mask( string $value ): bool {
		if ( $value === self::MASK ) {
			return true;
		}
		self::ensure_module_loaded();
		return class_exists( Module::class, false ) && $value === Module::getPasswordMask();
	}

	private static function ensure_module_loaded(): void {
		if ( class_exists( Module::class, false ) ) {
			return;
		}
		$module_file = dirname( __DIR__ ) . DIRECTORY_SEPARATOR . 'module.php';
		if ( is_readable( $module_file ) ) {
			require_once $module_file;
		}
	}

	/**
	 * Preserve existing ciphertext when UI posts the mask or an empty replace field.
	 *
	 * @param array<string, mixed> $incoming
	 * @param array<string, mixed> $existing
	 * @param list<string>         $secret_keys
	 * @return array<string, mixed>
	 */
	public static function merge_secrets( array $incoming, array $existing, array $secret_keys ): array {
		foreach ( $secret_keys as $key ) {
			$posted = isset( $incoming[ $key ] ) ? (string) $incoming[ $key ] : '';
			if ( $posted === '' || self::is_mask( $posted ) ) {
				$incoming[ $key ] = isset( $existing[ $key ] ) ? (string) $existing[ $key ] : '';
				continue;
			}
			if ( self::is_encrypted( $posted ) ) {
				continue;
			}
			$incoming[ $key ] = self::encrypt( $posted );
		}

		return $incoming;
	}

	/**
	 * @param array<string, mixed> $settings
	 * @param list<string>         $secret_keys
	 * @return array<string, mixed>
	 */
	public static function redact( array $settings, array $secret_keys ): array {
		foreach ( $secret_keys as $key ) {
			if ( ! empty( $settings[ $key ] ) ) {
				$settings[ $key ] = self::MASK;
			}
		}
		return $settings;
	}

	/**
	 * Documented constant map (setting key => constant name).
	 *
	 * @return array<string, string>
	 */
	public static function constant_map(): array {
		return [
			'provider'                => 'WP_POWERSUITE_MAIL_PROVIDER',
			'smtp_host'               => 'WP_POWERSUITE_SMTP_HOST',
			'smtp_port'               => 'WP_POWERSUITE_SMTP_PORT',
			'smtp_username'           => 'WP_POWERSUITE_SMTP_USERNAME',
			'smtp_password'           => 'WP_POWERSUITE_SMTP_PASSWORD',
			'sendgrid_api_key'        => 'WP_POWERSUITE_SENDGRID_API_KEY',
			'mailgun_api_key'         => 'WP_POWERSUITE_MAILGUN_API_KEY',
			'brevo_api_key'           => 'WP_POWERSUITE_BREVO_API_KEY',
			'postmark_server_token'   => 'WP_POWERSUITE_POSTMARK_SERVER_TOKEN',
			'mailersend_api_token'    => 'WP_POWERSUITE_MAILERSEND_API_TOKEN',
			'resend_api_key'          => 'WP_POWERSUITE_RESEND_API_KEY',
			'sparkpost_api_key'       => 'WP_POWERSUITE_SPARKPOST_API_KEY',
			'elastic_email_api_key'   => 'WP_POWERSUITE_ELASTIC_EMAIL_API_KEY',
			'smtp2go_api_key'         => 'WP_POWERSUITE_SMTP2GO_API_KEY',
			'mailjet_api_key'         => 'WP_POWERSUITE_MAILJET_API_KEY',
			'mailjet_secret_key'      => 'WP_POWERSUITE_MAILJET_SECRET_KEY',
			'netcore_api_key'         => 'WP_POWERSUITE_NETCORE_API_KEY',
			'mandrill_api_key'        => 'WP_POWERSUITE_MANDRILL_API_KEY',
			'emailit_api_key'         => 'WP_POWERSUITE_EMAILIT_API_KEY',
			'sendlayer_api_key'       => 'WP_POWERSUITE_SENDLAYER_API_KEY',
			'smtpcom_api_key'         => 'WP_POWERSUITE_SMTPCOM_API_KEY',
			'maileroo_api_key'        => 'WP_POWERSUITE_MAILEROO_API_KEY',
			'turbo_smtp_consumer_key' => 'WP_POWERSUITE_TURBO_SMTP_CONSUMER_KEY',
			'turbo_smtp_consumer_secret' => 'WP_POWERSUITE_TURBO_SMTP_CONSUMER_SECRET',
			'mail_baby_api_key'       => 'WP_POWERSUITE_MAIL_BABY_API_KEY',
			'aws_access_key_id'       => 'WP_POWERSUITE_AWS_ACCESS_KEY_ID',
			'aws_secret_access_key'   => 'WP_POWERSUITE_AWS_SECRET_ACCESS_KEY',
			'aws_region'              => 'WP_POWERSUITE_AWS_REGION',
			'google_client_id'        => 'WP_POWERSUITE_GOOGLE_CLIENT_ID',
			'google_client_secret'    => 'WP_POWERSUITE_GOOGLE_CLIENT_SECRET',
			'microsoft_client_id'     => 'WP_POWERSUITE_MICROSOFT_CLIENT_ID',
			'microsoft_client_secret' => 'WP_POWERSUITE_MICROSOFT_CLIENT_SECRET',
			'webhook_secret'               => 'WP_POWERSUITE_MAIL_WEBHOOK_SECRET',
			'webhook_bird_signing_secret'  => 'WP_POWERSUITE_BIRD_WEBHOOK_SECRET',
		];
	}

	/**
	 * Keys that must never be returned plaintext in admin/AJAX responses.
	 *
	 * @return list<string>
	 */
	public static function secret_keys(): array {
		return [
			'smtp_password',
			'sendgrid_api_key',
			'mailgun_api_key',
			'brevo_api_key',
			'postmark_server_token',
			'mailersend_api_token',
			'resend_api_key',
			'sparkpost_api_key',
			'elastic_email_api_key',
			'smtp2go_api_key',
			'mailjet_api_key',
			'mailjet_secret_key',
			'netcore_api_key',
			'mandrill_api_key',
			'emailit_api_key',
			'sendlayer_api_key',
			'smtpcom_api_key',
			'maileroo_api_key',
			'turbo_smtp_consumer_key',
			'turbo_smtp_consumer_secret',
			'mail_baby_api_key',
			'aws_access_key_id',
			'aws_secret_access_key',
			'google_client_secret',
			'google_access_token',
			'google_refresh_token',
			'microsoft_client_secret',
			'microsoft_access_token',
			'microsoft_refresh_token',
			'webhook_secret',
			'webhook_bird_signing_secret',
		];
	}
}
