<?php

namespace PloverCRM\Common;

/**
 * Canonical starter role templates used for first-run workspace setup.
 *
 * These templates are seeded one time and then behave like normal CRM roles,
 * with the exception of the protected super-admin template.
 */
class RoleTemplateRegistry
{
    public const SEED_VERSION = 5;

    public const TEMPLATE_SUPER_ADMIN = 'super_admin';
    public const TEMPLATE_MANAGER = 'manager';
    public const TEMPLATE_TEAMMATE = 'teammate';
    public const TEMPLATE_VIEWER = 'viewer';

    /**
     * Build the starter role payloads for the current workspace schema.
     *
     * @return array<int, array<string, mixed>>
     */
    public static function getStarterRolePayloads(): array
    {
        $fields = RoleManager::getAvailableFields();
        $fieldKeys = array_values(array_filter(array_map(static function ($field): string {
            if (is_array($field)) {
                return (string) ($field['slug'] ?? '');
            }

            return is_string($field) ? $field : '';
        }, $fields['standard'] ?? []), static fn(string $field): bool => $field !== ''));

        return [
            self::buildSuperAdminRole(),
            self::buildManagerRole($fieldKeys),
            self::buildTeammateRole($fieldKeys),
            self::buildViewerRole($fieldKeys),
        ];
    }

    public static function getTemplate(string $templateKey): ?array
    {
        foreach (self::getStarterRolePayloads() as $template) {
            if (($template['template_key'] ?? null) === $templateKey) {
                return $template;
            }
        }

        return null;
    }

    private static function buildSuperAdminRole(): array
    {
        return [
            'id' => 'starter-super-admin',
            'name' => 'Super Admin',
            'slug' => RoleManager::SUPER_ADMIN_SLUG,
            'template_key' => self::TEMPLATE_SUPER_ADMIN,
            'is_system_seeded' => true,
            'is_protected' => true,
            'is_template_pristine' => true,
            'template_version' => self::SEED_VERSION,
            'sort_order' => 10,
            'is_super_admin' => true,
            'can_delete_contacts' => true,
            'view_scope' => RoleManager::SCOPE_ALL,
            'update_scope' => RoleManager::SCOPE_ALL,
            'field_permissions' => [],
            'custom_field_permissions' => [],
            'tracking_permissions' => self::buildTrackingPermissions(true),
            'entity_permissions' => [],
            'capabilities' => CapabilityRegistry::getAllCapabilityKeys(),
        ];
    }

    private static function buildManagerRole(array $fieldKeys): array
    {
        return [
            'id' => 'starter-manager',
            'name' => 'Manager',
            'slug' => 'plover_crm_manager',
            'template_key' => self::TEMPLATE_MANAGER,
            'is_system_seeded' => true,
            'is_protected' => false,
            'is_template_pristine' => true,
            'template_version' => self::SEED_VERSION,
            'sort_order' => 20,
            'is_super_admin' => false,
            'can_delete_contacts' => true,
            'view_scope' => RoleManager::SCOPE_ALL,
            'update_scope' => RoleManager::SCOPE_ALL,
            'field_permissions' => self::buildFieldPermissions($fieldKeys, true, true, true),
            'custom_field_permissions' => [],
            'tracking_permissions' => self::buildTrackingPermissions(true),
            'entity_permissions' => self::buildEntityPermissions([
                'notes' => ['create', 'read', 'update', 'delete'],
                'list_definitions' => ['create', 'read', 'update', 'delete'],
                'tag_definitions' => ['create', 'read', 'update', 'delete'],
            ]),
            'capabilities' => self::buildSettingCapabilities([
                'business_information' => ['view', 'manage'],
                'custom_fields' => ['view', 'manage'],
                'stages' => ['view', 'manage'],
                'notification_templates' => ['view', 'manage'],
                'lead_table' => ['view', 'manage'],
                'crm' => ['view'],
            ]),
        ];
    }

    private static function buildTeammateRole(array $fieldKeys): array
    {
        return [
            'id' => 'starter-teammate',
            'name' => 'Teammate',
            'slug' => 'plover_crm_teammate',
            'template_key' => self::TEMPLATE_TEAMMATE,
            'is_system_seeded' => true,
            'is_protected' => false,
            'is_template_pristine' => true,
            'template_version' => self::SEED_VERSION,
            'sort_order' => 30,
            'is_super_admin' => false,
            'can_delete_contacts' => false,
            'view_scope' => RoleManager::SCOPE_ALL,
            'update_scope' => RoleManager::SCOPE_OWNED,
            'field_permissions' => self::buildFieldPermissions($fieldKeys, true, true, true),
            'custom_field_permissions' => [],
            'tracking_permissions' => self::buildTrackingPermissions(true),
            'entity_permissions' => self::buildEntityPermissions([
                'notes' => ['create', 'read', 'update', 'delete'],
            ]),
            'capabilities' => [],
        ];
    }

    private static function buildViewerRole(array $fieldKeys): array
    {
        return [
            'id' => 'starter-viewer',
            'name' => 'Viewer',
            'slug' => 'plover_crm_viewer',
            'template_key' => self::TEMPLATE_VIEWER,
            'is_system_seeded' => true,
            'is_protected' => false,
            'is_template_pristine' => true,
            'template_version' => self::SEED_VERSION,
            'sort_order' => 40,
            'is_super_admin' => false,
            'can_delete_contacts' => false,
            'view_scope' => RoleManager::SCOPE_ALL,
            'update_scope' => RoleManager::SCOPE_OWNED,
            'field_permissions' => self::buildFieldPermissions($fieldKeys, false, true, false),
            'custom_field_permissions' => [],
            'tracking_permissions' => self::buildTrackingPermissions(true),
            'entity_permissions' => self::buildEntityPermissions([
                'notes' => ['read'],
                'list_definitions' => ['read'],
                'tag_definitions' => ['read'],
            ]),
            'capabilities' => [],
        ];
    }

    /**
     * @param array<int, string> $fieldKeys
     * @return array<string, array<string, bool>>
     */
    private static function buildFieldPermissions(
        array $fieldKeys,
        bool $canCreate,
        bool $canRead,
        bool $canUpdate
    ): array {
        $permissions = [];

        foreach ($fieldKeys as $fieldKey) {
            if ($fieldKey === '') {
                continue;
            }

            $permissions[$fieldKey] = [
                'create' => $canCreate,
                'read' => $canRead,
                'update' => $canUpdate,
            ];
        }

        return $permissions;
    }

    /**
     * @param array<string, array<int, string>> $enabledActions
     * @return array<string, array<string, bool>>
     */
    private static function buildEntityPermissions(array $enabledActions): array
    {
        $permissions = [];

        foreach (RoleManager::ENTITIES as $entity => $actions) {
            $permissions[$entity] = [];

            foreach ($actions as $action) {
                $permissions[$entity][$action] = in_array($action, $enabledActions[$entity] ?? [], true);
            }
        }

        return $permissions;
    }

    /**
     * @return array<string, array<string, bool>>
     */
    private static function buildTrackingPermissions(bool $canRead): array
    {
        return [
            \PloverCRM\Core\Services\SystemFieldRegistry::TRACKING_PERMISSION_CONTACT_DATA => [
                'read' => $canRead,
            ],
            \PloverCRM\Core\Services\SystemFieldRegistry::TRACKING_PERMISSION_IP_INFORMATION => [
                'read' => $canRead,
            ],
        ];
    }

    /**
     * @param array<string, array<int, string>> $settingActions
     * @return array<int, string>
     */
    private static function buildSettingCapabilities(array $settingActions): array
    {
        $capabilities = [];

        foreach ($settingActions as $settingKey => $actions) {
            foreach ($actions as $action) {
                $capability = CapabilityRegistry::getSettingCapabilityOrNull($settingKey, $action);

                if (!$capability) {
                    continue;
                }

                $capabilities[] = $capability;
            }
        }

        return CapabilityRegistry::expandCapabilities($capabilities);
    }
}
