<?php

declare(strict_types=1);

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class RoleAndPermissionSeeder extends Seeder
{
    /**
     * All granular permissions grouped by category.
     *
     * @var array<string, list<string>>
     */
    private const PERMISSION_GROUPS = [
        'customers' => [
            'customers.view',
            'customers.edit',
            'customers.create',
            'customers.delete',
            'customers.suspend',
            'customers.impersonate',
        ],
        'services' => [
            'services.view',
            'services.suspend',
            'services.terminate',
            'services.provision',
            'services.extend',
        ],
        'invoices' => [
            'invoices.view',
            'invoices.create',
            'invoices.edit',
            'invoices.void',
            'invoices.refund',
        ],
        'tickets' => [
            'tickets.view',
            'tickets.reply',
            'tickets.assign',
            'tickets.close',
            'tickets.delete',
        ],
        'reports' => [
            'reports.view',
            'reports.export',
        ],
        'settings' => [
            'settings.view',
            'settings.edit',
        ],
        'audit_logs' => [
            'audit_logs.view',
            'audit_logs.export',
        ],
        'plans' => [
            'plans.view',
            'plans.create',
            'plans.edit',
            'plans.delete',
        ],
        'coupons' => [
            'coupons.view',
            'coupons.create',
            'coupons.edit',
            'coupons.delete',
        ],
        'credit_notes' => [
            'credit_notes.view',
            'credit_notes.create',
            'credit_notes.void',
        ],
        'debit_notes' => [
            'debit_notes.view',
            'debit_notes.create',
            'debit_notes.void',
        ],
        'affiliates' => [
            'affiliates.view',
            'affiliates.approve',
            'affiliates.payout',
        ],
        'staff' => [
            'staff.view',
            'staff.manage',
        ],
    ];

    /**
     * Legacy permissions for backward compatibility.
     *
     * @var list<string>
     */
    private const LEGACY_PERMISSIONS = [
        'manage users',
        'manage services',
        'manage plans',
        'manage invoices',
        'manage coupons',
        'view audit logs',
        'impersonate users',
    ];

    public function run(): void
    {
        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

        // Create legacy permissions (idempotent)
        foreach (self::LEGACY_PERMISSIONS as $permission) {
            Permission::firstOrCreate(['name' => $permission, 'guard_name' => 'web']);
        }

        // Create all granular permissions (idempotent)
        foreach (self::PERMISSION_GROUPS as $permissions) {
            foreach ($permissions as $permission) {
                Permission::firstOrCreate(['name' => $permission, 'guard_name' => 'web']);
            }
        }

        $allPermissions = Permission::where('guard_name', 'web')->pluck('name')->toArray();

        // admin — ALL permissions
        $adminRole = Role::firstOrCreate(['name' => 'admin', 'guard_name' => 'web']);
        $adminRole->syncPermissions($allPermissions);

        // customer — no permissions
        Role::firstOrCreate(['name' => 'customer', 'guard_name' => 'web']);

        // super_admin — ALL permissions
        $superAdmin = Role::firstOrCreate(['name' => 'super_admin', 'guard_name' => 'web']);
        $superAdmin->syncPermissions($allPermissions);

        // billing_admin
        $billingAdmin = Role::firstOrCreate(['name' => 'billing_admin', 'guard_name' => 'web']);
        $billingAdmin->syncPermissions([
            'customers.view', 'customers.edit',
            'invoices.view', 'invoices.create', 'invoices.edit', 'invoices.void', 'invoices.refund',
            'services.view', 'services.suspend',
            'reports.view', 'reports.export',
            'credit_notes.view', 'credit_notes.create', 'credit_notes.void',
            'debit_notes.view', 'debit_notes.create', 'debit_notes.void',
            'plans.view',
        ]);

        // support_agent
        $supportAgent = Role::firstOrCreate(['name' => 'support_agent', 'guard_name' => 'web']);
        $supportAgent->syncPermissions([
            'customers.view',
            'tickets.view', 'tickets.reply',
            'services.view',
        ]);

        // support_lead
        $supportLead = Role::firstOrCreate(['name' => 'support_lead', 'guard_name' => 'web']);
        $supportLead->syncPermissions([
            'customers.view', 'customers.edit',
            'tickets.view', 'tickets.reply', 'tickets.assign', 'tickets.close', 'tickets.delete',
            'services.view',
        ]);

        // readonly_admin — all *.view permissions only
        $readonlyAdmin = Role::firstOrCreate(['name' => 'readonly_admin', 'guard_name' => 'web']);
        $allGranular = collect(self::PERMISSION_GROUPS)->flatten()->toArray();
        $viewPermissions = collect($allGranular)->filter(fn (string $p): bool => str_ends_with($p, '.view'))->toArray();
        $readonlyAdmin->syncPermissions($viewPermissions);

        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
    }
}
