<?php

/**
 * Sentinel_Onboarding_Presets
 *
 * Maps Quick Setup wizard profile + privacy choices onto sentinel_log_management
 * option patches for preview and apply (Phase 2).
 */

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

class Sentinel_Onboarding_Presets
{

    /** @var string[] */
    const PROFILE_KEYS = array('recommended', 'quiet', 'security', 'performance');

    /** @var string[] */
    const PRIVACY_KEYS = array('standard', 'privacy_conscious', 'minimal');

    /**
     * Settings keys shown in the review table when they differ after applying patches.
     *
     * @return string[]
     */
    public static function review_keys()
    {
        return array(
            'anonymize_schedule',
            'log_ip_addresses',
            'sentinel_email_notifications_enabled',
            'batch_logging_enabled',
            'rate_limit_behavior',
            'excluded_user_roles',
            'right_to_be_forgotten',
            'data_portability',
            'sentinel_email_daily_summary',
            'sentinel_email_realtime_critical',
            'sentinel_email_realtime_security',
            'sentinel_email_realtime_error',
            'sentinel_email_realtime_high',
        );
    }

    /**
     * Default sentinel_log_management shape (minimal superset used by onboarding).
     * Matches admin/views/settings-page.php defaults for touched keys only.
     *
     * @return array<string, mixed>
     */
    private static function default_settings_skeleton()
    {
        return array(
            'batch_logging_enabled'                => 0,
            'batch_size'                           => 50,
            'batch_frequency'                      => 60,
            'rate_limit_behavior'                  => 'graceful_degradation',
            'excluded_user_roles'                  => array('administrator'),
            'log_ip_addresses'                     => 1,
            'anonymize_schedule'                   => 30,
            'right_to_be_forgotten'               => 0,
            'data_portability'                    => 0,
            'sentinel_email_notifications_enabled' => 0,
            'sentinel_email_realtime_critical'    => 0,
            'sentinel_email_realtime_security'     => 0,
            'sentinel_email_realtime_error'        => 0,
            'sentinel_email_realtime_high'         => 0,
            'sentinel_email_daily_summary'         => 0,
            'sentinel_email_daily_error'           => 0,
            'sentinel_email_daily_user'            => 0,
            'sentinel_email_weekly_health'         => 0,
            'sentinel_email_weekly_performance'    => 0,
            'sentinel_email_weekly_security'       => 0,
        );
    }

    /**
     * Current settings merged onto skeleton so missing keys have stable baselines.
     *
     * @return array<string, mixed>
     */
    public static function baseline_settings()
    {
        $stored = get_option('sentinel_log_management', array());
        if (!is_array($stored)) {
            $stored = array();
        }
        return wp_parse_args($stored, self::default_settings_skeleton());
    }

    /**
     * Normalise a value for strict comparison (diff).
     *
     * @param mixed $val
     */
    public static function normalize_for_compare($key, $val)
    {
        if ($key === 'excluded_user_roles') {
            $arr = is_array($val) ? $val : array_filter(array_map('trim', explode(',', (string) $val)));
            $arr = array_map('strtolower', $arr);
            sort($arr);
            return implode(',', $arr);
        }
        if ($key === 'rate_limit_behavior') {
            return (string) $val;
        }
        if ($key === 'anonymize_schedule') {
            return (string) (int) $val;
        }
        if (strpos($key, 'sentinel_email_', 0) === 0
            || in_array($key, array('log_ip_addresses', 'batch_logging_enabled', 'right_to_be_forgotten', 'data_portability'), true)
        ) {
            $on = ($val === true || (string) $val === 'true' || (int) $val === 1);
            return $on ? '1' : '0';
        }

        return (string) $val;
    }

    /**
     * @return bool
     */
    public static function values_differ($key, $a, $b)
    {
        return self::normalize_for_compare($key, $a) !== self::normalize_for_compare($key, $b);
    }

    /**
     * @param string $key
     * @param mixed $value
     * @return string|int Suitable for JSON (JS formats for display).
     */
    public static function raw_for_transport($key, $value)
    {
        if ($key === 'excluded_user_roles') {
            if (is_array($value)) {
                return implode(',', $value);
            }
            return (string) $value;
        }
        if ($key === 'rate_limit_behavior') {
            return (string) $value;
        }
        if ($key === 'anonymize_schedule') {
            return (string) (int) $value;
        }
        if (strpos($key, 'sentinel_email_', 0) === 0
            || in_array($key, array('log_ip_addresses', 'batch_logging_enabled', 'right_to_be_forgotten', 'data_portability'), true)
        ) {
            return ($value === true || (string) $value === 'true' || (int) $value === 1) ? 1 : 0;
        }

        return (string) $value;
    }

    /** @param string $profile */
    public static function profile_patch($profile)
    {
        switch ($profile) {
            case 'recommended':
                return array(
                    'anonymize_schedule'                   => 90,
                    'sentinel_email_notifications_enabled' => 1,
                    'sentinel_email_realtime_critical'     => 1,
                    'sentinel_email_realtime_security'     => 1,
                    'sentinel_email_realtime_error'        => 0,
                    'sentinel_email_realtime_high'         => 0,
                    'sentinel_email_daily_summary'          => 0,
                    'sentinel_email_daily_error'           => 0,
                    'sentinel_email_daily_user'            => 0,
                    'sentinel_email_weekly_health'         => 0,
                    'sentinel_email_weekly_performance'     => 0,
                    'sentinel_email_weekly_security'       => 0,
                );

            case 'quiet':
                return array(
                    'anonymize_schedule'                   => 90,
                    'sentinel_email_notifications_enabled' => 1,
                    'sentinel_email_realtime_critical'     => 0,
                    'sentinel_email_realtime_security'     => 0,
                    'sentinel_email_realtime_error'        => 0,
                    'sentinel_email_realtime_high'         => 0,
                    'sentinel_email_daily_summary'          => 1,
                    'sentinel_email_daily_error'           => 0,
                    'sentinel_email_daily_user'            => 0,
                    'sentinel_email_weekly_health'         => 0,
                    'sentinel_email_weekly_performance'     => 0,
                    'sentinel_email_weekly_security'       => 0,
                );

            case 'security':
                return array(
                    'anonymize_schedule'                   => 30,
                    'sentinel_email_notifications_enabled' => 1,
                    'sentinel_email_realtime_critical'     => 1,
                    'sentinel_email_realtime_security'     => 1,
                    'sentinel_email_realtime_error'        => 1,
                    'sentinel_email_realtime_high'        => 0,
                    'sentinel_email_daily_summary'        => 0,
                    'sentinel_email_daily_error'           => 0,
                    'sentinel_email_daily_user'            => 0,
                    'sentinel_email_weekly_health'         => 0,
                    'sentinel_email_weekly_performance'     => 0,
                    'sentinel_email_weekly_security'       => 0,
                );

            case 'performance':
                return array(
                    'anonymize_schedule'                   => 90,
                    'batch_logging_enabled'                => 1,
                    'batch_size'                           => 50,
                    'batch_frequency'                       => 60,
                    'rate_limit_behavior'                  => 'graceful_degradation',
                );

            default:
                return array();
        }
    }

    /** @param string $privacy */
    public static function privacy_patch($privacy)
    {
        switch ($privacy) {
            case 'standard':
                return array(
                    'log_ip_addresses'       => 1,
                    'anonymize_schedule'      => 90,
                    'right_to_be_forgotten'   => 0,
                    'data_portability'        => 0,
                );

            case 'privacy_conscious':
                return array(
                    'log_ip_addresses'       => 1,
                    'anonymize_schedule'      => 30,
                    'right_to_be_forgotten'   => 1,
                    'data_portability'        => 1,
                );

            case 'minimal':
                return array(
                    'log_ip_addresses'       => 0,
                    'anonymize_schedule'      => 30,
                    'right_to_be_forgotten'   => 1,
                    'data_portability'        => 1,
                );

            default:
                return array();
        }
    }

    /**
     * Keep API credentials when other settings flows overwrite sentinel_log_management.
     *
     * @param array<string,mixed> $settings Candidate option payload.
     * @param array<string,mixed>|null $current Stored option; defaults to live option.
     * @return array<string,mixed>
     */
    public static function preserve_api_settings(array $settings, $current = null)
    {
        if ($current === null) {
            $current = get_option('sentinel_log_management', array());
        }
        if (!is_array($current)) {
            $current = array();
        }

        if (!empty($current['api_key'])) {
            $settings['api_key'] = $current['api_key'];
        }

        if (array_key_exists('api_access', $current)) {
            $settings['api_access'] = (int) !empty($current['api_access']);
        }

        return $settings;
    }

    /**
     * Composed settings after profile then privacy overlays.
     *
     * @param string $profile_key
     * @param string $privacy_key
     * @return array<string, mixed>
     */
    public static function compose($profile_key, $privacy_key)
    {
        $base = self::baseline_settings();
        $p    = self::profile_patch($profile_key);
        $pv   = self::privacy_patch($privacy_key);

        return self::preserve_api_settings(array_merge($base, $p, $pv), $base);
    }

    /**
     * Build rows for AJAX preview: only keys whose value differs from baseline.
     *
     * @param array<string,mixed> $after
     * @return array<int,array{key:string,now:string|int,after:string|int,changed:bool}>
     */
    public static function diff_rows(array $after)
    {
        $base = self::baseline_settings();
        $rows = array();

        foreach (self::review_keys() as $key) {
            if (!array_key_exists($key, $base) || !array_key_exists($key, $after)) {
                continue;
            }
            $now_val   = $base[ $key ];
            $after_val = $after[ $key ];

            if (! self::values_differ($key, $now_val, $after_val)) {
                continue;
            }

            $rows[] = array(
                'key'     => $key,
                'now'     => self::raw_for_transport($key, $now_val),
                'after'   => self::raw_for_transport($key, $after_val),
                'changed' => true,
            );
        }

        return $rows;
    }
}
