<?php

namespace PloverCRM\Common;

/**
 * Canonical workspace capability registry.
 *
 * Capabilities describe what a CRM role may do inside the workspace. They are
 * client-agnostic and are consumed by the plugin, standalone web app, and
 * mobile app from the same contract.
 */
class CapabilityRegistry
{
    /**
     * Shared workspace settings that can be granted to non-admin CRM roles.
     */
    private const SETTINGS = [
        'users' => [
            'label' => 'Users',
            'description' => 'CRM teammate accounts, assigned roles, and sign-in details.',
            'actions' => ['view', 'manage'],
        ],
        'roles' => [
            'label' => 'Roles',
            'description' => 'CRM roles, scopes, and permission matrices for teammates.',
            'actions' => ['view', 'manage'],
        ],
        'crm' => [
            'label' => 'CRM',
            'description' => 'CRM provider selection and shared reply-to email defaults.',
            'actions' => ['view', 'manage'],
        ],
        'lead_table' => [
            'label' => 'Lead Table',
            'description' => 'Shared contact-table columns used across the workspace.',
            'actions' => ['view', 'manage'],
        ],
        'business_information' => [
            'label' => 'Business Information',
            'description' => 'Shared business details used in templates and quick replies.',
            'actions' => ['view', 'manage'],
        ],
        'custom_fields' => [
            'label' => 'Custom Fields',
            'description' => 'Workspace-specific lead fields and their configuration.',
            'actions' => ['view', 'manage'],
        ],
        'stages' => [
            'label' => 'Stages',
            'description' => 'Pipeline stages, ordering, and stage colors.',
            'actions' => ['view', 'manage'],
        ],
        'notification_templates' => [
            'label' => 'Notification Templates',
            'description' => 'Shared alert titles and messages for new leads and reminders.',
            'actions' => ['view', 'manage'],
        ],
    ];

    public static function getSettingDefinitions(): array
    {
        $definitions = [];

        foreach (self::SETTINGS as $key => $setting) {
            $definitions[] = [
                'key' => $key,
                'label' => $setting['label'],
                'description' => $setting['description'],
                'actions' => $setting['actions'],
            ];
        }

        return $definitions;
    }

    public static function getAllCapabilityKeys(): array
    {
        $capabilities = [];

        foreach (self::SETTINGS as $settingKey => $setting) {
            foreach ($setting['actions'] as $action) {
                $capabilities[] = self::getSettingCapability($settingKey, $action);
            }
        }

        return $capabilities;
    }

    public static function getAssignableCapabilityKeys(): array
    {
        return self::getAllCapabilityKeys();
    }

    public static function isValidCapability(string $capability): bool
    {
        return in_array($capability, self::getAllCapabilityKeys(), true);
    }

    public static function isAssignableCapability(string $capability): bool
    {
        return in_array($capability, self::getAssignableCapabilityKeys(), true);
    }

    public static function getSettingCapability(string $settingKey, string $action): string
    {
        return sprintf('settings.%s.%s', sanitize_key($settingKey), sanitize_key($action));
    }

    public static function getSettingCapabilityOrNull(string $settingKey, string $action): ?string
    {
        $settingKey = sanitize_key($settingKey);
        $action = sanitize_key($action);

        $setting = self::SETTINGS[$settingKey] ?? null;

        if (!$setting || !in_array($action, $setting['actions'], true)) {
            return null;
        }

        return self::getSettingCapability($settingKey, $action);
    }

    /**
     * Managing a shared setting always implies view access to the same setting.
     */
    public static function expandCapabilities(array $capabilities): array
    {
        $expanded = [];

        foreach ($capabilities as $capability) {
            $capability = sanitize_text_field((string) $capability);

            if ($capability === '' || !self::isValidCapability($capability)) {
                continue;
            }

            $expanded[$capability] = true;

            if (str_ends_with($capability, '.manage')) {
                $expanded[str_replace('.manage', '.view', $capability)] = true;
            }
        }

        return array_keys($expanded);
    }
}
