<?php

declare(strict_types=1);

namespace Database\Seeders;

use PDO;

/**
 * RolePermissionSeeder
 *
 * Reads config/permissions.php as the single source of truth: expands
 * every module's action list into `permissions` rows, creates the four
 * system roles shown in User Management / Roles & Permissions, then
 * maps each role to permissions according to default_role_matrix
 * ('full' = every action in the module, 'view' = view-only, 'none' =
 * nothing).
 */
final class RolePermissionSeeder implements SeederInterface
{
    public function run(PDO $pdo): void
    {
        $config = require dirname(__DIR__, 2) . '/config/permissions.php';

        $permissionIds = $this->seedPermissions($pdo, $config['modules']);
        $roleIds = $this->seedRoles($pdo);
        $this->seedRolePermissions($pdo, $roleIds, $permissionIds, $config['modules'], $config['default_role_matrix']);
    }

    private function seedPermissions(PDO $pdo, array $modules): array
    {
        $stmt = $pdo->prepare(
            'INSERT INTO permissions (module, action, slug, description, created_at)
             VALUES (:module, :action, :slug, :description, NOW())
             ON DUPLICATE KEY UPDATE description = VALUES(description)'
        );

        $ids = [];
        $count = 0;

        foreach ($modules as $moduleSlug => $module) {
            foreach ($module['actions'] as $action) {
                $slug = "{$moduleSlug}.{$action}";
                $stmt->execute([
                    'module' => $moduleSlug,
                    'action' => $action,
                    'slug' => $slug,
                    'description' => "{$module['label']} — " . ucfirst($action),
                ]);
                $count++;
            }
        }

        $ids = $pdo->query('SELECT slug, id FROM permissions')->fetchAll(PDO::FETCH_KEY_PAIR);
        $ids = array_map('intval', $ids);

        echo "  seeded {$count} permissions\n";

        return $ids;
    }

    private function seedRoles(PDO $pdo): array
    {
        $roles = [
            ['name' => 'Operations Admin', 'slug' => 'operations_admin', 'description' => 'Full access across both business lines.', 'is_system' => 1],
            ['name' => 'Sales Rep', 'slug' => 'sales_rep', 'description' => 'Leads, customers, scheduling, and campaigns for their assigned business line(s).', 'is_system' => 1],
            ['name' => 'Field Staff', 'slug' => 'field_staff', 'description' => 'Caregivers and crew — appointments and their own schedule only.', 'is_system' => 1],
            ['name' => 'Read-Only', 'slug' => 'read_only', 'description' => 'View-only access for auditors, accountants, and stakeholders.', 'is_system' => 1],
        ];

        $stmt = $pdo->prepare(
            'INSERT INTO roles (name, slug, description, is_system, created_at, updated_at)
             VALUES (:name, :slug, :description, :is_system, NOW(), NOW())
             ON DUPLICATE KEY UPDATE description = VALUES(description)'
        );

        foreach ($roles as $role) {
            $stmt->execute($role);
        }

        $ids = $pdo->query('SELECT slug, id FROM roles')->fetchAll(PDO::FETCH_KEY_PAIR);
        $ids = array_map('intval', $ids);

        echo '  seeded ' . count($roles) . " system roles\n";

        return $ids;
    }

    private function seedRolePermissions(PDO $pdo, array $roleIds, array $permissionIds, array $modules, array $matrix): void
    {
        $insert = $pdo->prepare(
            'INSERT IGNORE INTO role_permissions (role_id, permission_id, created_at) VALUES (:role_id, :permission_id, NOW())'
        );

        $count = 0;

        foreach ($matrix as $roleSlug => $moduleLevels) {
            if (!isset($roleIds[$roleSlug])) {
                continue;
            }
            $roleId = $roleIds[$roleSlug];

            foreach ($moduleLevels as $moduleSlug => $level) {
                if ($level === 'none' || !isset($modules[$moduleSlug])) {
                    continue;
                }

                $actionsToGrant = $level === 'full'
                    ? $modules[$moduleSlug]['actions']
                    : array_intersect(['view'], $modules[$moduleSlug]['actions']);

                foreach ($actionsToGrant as $action) {
                    $slug = "{$moduleSlug}.{$action}";
                    if (!isset($permissionIds[$slug])) {
                        continue;
                    }

                    $insert->execute(['role_id' => $roleId, 'permission_id' => $permissionIds[$slug]]);
                    $count++;
                }
            }
        }

        echo "  mapped {$count} role-permission grants\n";
    }
}
