<?php

namespace WPSN\Core;

defined('ABSPATH') || exit;

/**
 * Capabilities & roles for WP SEO Next.
 *
 * Goal:
 * - Keep editor UX working via native edit_post/edit_term caps.
 * - Provide an optional SEO Manager role for agency/client workflows.
 * - Allow granular access to WP SEO Next admin screens (Settings + Tools).
 */
final class Capabilities
{
    /** Option used to store the last version that installed/updated caps. */
    private const OPTION_NAME = 'wpsn_caps_version';

    // Admin screens (Settings + Tools)
    public const CAP_SETTINGS   = 'wpsn_manage_settings';
    public const CAP_TOOLS      = 'wpsn_manage_tools';

    // Licensing / entitlements (admin-only by default)
    public const CAP_LICENSE    = 'wpsn_manage_license';

    // High-impact tools
    public const CAP_REDIRECTS  = 'wpsn_manage_redirects';
    public const CAP_CONFIG     = 'wpsn_manage_config_sync';

    // Integrations/tools
    public const CAP_GSC        = 'wpsn_manage_gsc';
    public const CAP_INDEXNOW   = 'wpsn_manage_indexnow';
    public const CAP_AI_ADMIN   = 'wpsn_manage_ai';

    // Usage caps
    public const CAP_USE_AI     = 'wpsn_use_ai';

    /** Per-user override for external AI usage (OpenAI). Values: allow|deny (missing = inherit). */
    public const USERMETA_AI_USE_OVERRIDE = '_wpsn_ai_use_override';

    /** Per-user override for AI admin/tools access. Values: allow|deny (missing = inherit). */
    public const USERMETA_AI_MANAGE_OVERRIDE = '_wpsn_ai_manage_override';

    /**
     * Install/upgrade caps (safe to call repeatedly).
     */
    public static function maybeInstall(): void
    {
        $installed = get_option(self::OPTION_NAME, '');
        $installed = is_string($installed) ? $installed : '';

        if ($installed === (string) WPSN_VERSION) {
            return;
        }

        self::install();

        update_option(self::OPTION_NAME, (string) WPSN_VERSION, false);
    }

    public static function install(): void
    {
        // Ensure admin has all caps.
        $admin = get_role('administrator');
        if ($admin) {
            foreach (self::allCaps() as $cap) {
                $admin->add_cap($cap);
            }
        }

        // Create a dedicated SEO Manager role for agencies/teams.
        // Keep it minimal by default: Tools + Redirects + GSC + IndexNow + AI usage.
        $roleId = 'wpsn_seo_manager';
        if (!get_role($roleId)) {
            add_role($roleId, __('SEO Manager', 'wp-seo-next'), [
                'read' => true,
                self::CAP_TOOLS => true,
                self::CAP_REDIRECTS => true,
                self::CAP_GSC => true,
                self::CAP_INDEXNOW => true,
                self::CAP_USE_AI => true,
            ]);
        } else {
            // Ensure caps exist on role if it already existed (upgrade).
            $role = get_role($roleId);
            if ($role) {
                foreach ([self::CAP_TOOLS, self::CAP_REDIRECTS, self::CAP_GSC, self::CAP_INDEXNOW, self::CAP_USE_AI] as $cap) {
                    $role->add_cap($cap);
                }
            }
        }
    }

    /**
     * @return string[]
     */
    public static function allCaps(): array
    {
        return [
            self::CAP_SETTINGS,
            self::CAP_TOOLS,
            self::CAP_LICENSE,
            self::CAP_REDIRECTS,
            self::CAP_CONFIG,
            self::CAP_GSC,
            self::CAP_INDEXNOW,
            self::CAP_AI_ADMIN,
            self::CAP_USE_AI,
        ];
    }

    /**
     * Licensing screen access.
     */
    public static function canManageLicense(): bool
    {
        return current_user_can('manage_options') || current_user_can(self::CAP_LICENSE);
    }

    /**
     * Settings screen access.
     */
    public static function canManageSettings(): bool
    {
        // Back-compat: admins always pass.
        return current_user_can('manage_options') || current_user_can(self::CAP_SETTINGS);
    }

    /**
     * Generic tools access (Bulk, Audit, Validators, Privacy, etc.).
     */
    public static function canManageTools(): bool
    {
        return current_user_can('manage_options') || current_user_can(self::CAP_TOOLS);
    }

    public static function canManageRedirects(): bool
    {
        return current_user_can('manage_options') || current_user_can(self::CAP_REDIRECTS);
    }

    public static function canManageConfigSync(): bool
    {
        return current_user_can('manage_options') || current_user_can(self::CAP_CONFIG);
    }

    public static function canManageGsc(): bool
    {
        return current_user_can('manage_options') || current_user_can(self::CAP_GSC);
    }

    public static function canManageIndexNow(): bool
    {
        return current_user_can('manage_options') || current_user_can(self::CAP_INDEXNOW);
    }

    public static function canManageAIAdmin(): bool
    {
        // Site admins always have access.
        if (current_user_can('manage_options')) {
            return true;
        }

        $userId = (int) get_current_user_id();
        if ($userId <= 0) {
            return false;
        }

        // Per-user override (wins over role caps).
        $override = self::getUserAIManageOverride($userId);
        if ($override === 'deny') {
            return false;
        }
        if ($override === 'allow') {
            return true;
        }

        return current_user_can(self::CAP_AI_ADMIN);
    }

    /**
     * External AI usage (OpenAI) – used for REST + bulk generation gating.
     */
    public static function canUseAI(): bool
    {
        $userId = (int) get_current_user_id();
        if ($userId <= 0) {
            return false;
        }

        // Per-user override (wins over role caps).
        $override = self::getUserAIUseOverride($userId);
        if ($override === 'deny') {
            return false;
        }
        if ($override === 'allow') {
            return true;
        }

        return current_user_can('manage_options') || current_user_can(self::CAP_USE_AI);
    }

    /**
     * Get per-user external AI override.
     *
     * @return 'allow'|'deny'|'inherit'
     */
    public static function getUserAIUseOverride(int $userId): string
    {
        $userId = (int) $userId;
        if ($userId <= 0) {
            return 'inherit';
        }

        $v = get_user_meta($userId, self::USERMETA_AI_USE_OVERRIDE, true);
        $v = is_string($v) ? sanitize_key($v) : '';

        if (in_array($v, ['allow', 'deny'], true)) {
            return $v;
        }

        return 'inherit';
    }

    /**
     * Set per-user external AI override. Use empty/"inherit" to clear.
     */
    public static function setUserAIUseOverride(int $userId, string $mode): void
    {
        $userId = (int) $userId;
        if ($userId <= 0) {
            return;
        }

        $mode = sanitize_key((string) $mode);
        if ($mode === '' || $mode === 'inherit') {
            delete_user_meta($userId, self::USERMETA_AI_USE_OVERRIDE);
            return;
        }

        if (!in_array($mode, ['allow', 'deny'], true)) {
            return;
        }

        update_user_meta($userId, self::USERMETA_AI_USE_OVERRIDE, $mode);
    }

    /**
     * Get per-user AI admin/tools override.
     *
     * @return 'allow'|'deny'|'inherit'
     */
    public static function getUserAIManageOverride(int $userId): string
    {
        $userId = (int) $userId;
        if ($userId <= 0) {
            return 'inherit';
        }

        $v = get_user_meta($userId, self::USERMETA_AI_MANAGE_OVERRIDE, true);
        $v = is_string($v) ? sanitize_key($v) : '';

        if (in_array($v, ['allow', 'deny'], true)) {
            return $v;
        }

        return 'inherit';
    }

    /**
     * Set per-user AI admin/tools override. Use empty/"inherit" to clear.
     */
    public static function setUserAIManageOverride(int $userId, string $mode): void
    {
        $userId = (int) $userId;
        if ($userId <= 0) {
            return;
        }

        $mode = sanitize_key((string) $mode);
        if ($mode === '' || $mode === 'inherit') {
            delete_user_meta($userId, self::USERMETA_AI_MANAGE_OVERRIDE);
            return;
        }

        if (!in_array($mode, ['allow', 'deny'], true)) {
            return;
        }

        update_user_meta($userId, self::USERMETA_AI_MANAGE_OVERRIDE, $mode);
    }
}
