<?php

namespace App\Services;

use App\Models\User;
use Database\Seeders\RoleSeeder;
use ReflectionClass;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;

class MalawiTerritoryCompanyAdminService
{
    public const COMPANY_SLUG = MalawiTerritoryRosterSync::COMPANY_SLUG;

    public const COMPANY_ADMIN_EMAIL = 'salvationarmy@gmail.com';

    /**
     * Grant the territory company account the full company (system) permission set.
     *
     * @return array{permissions: int, email: string}
     */
    public function ensureFullSystemAccess(?User $company = null): array
    {
        $company = $company ?? $this->resolveCompanyUser();

        $permissionNames = $this->companyPermissionNames();

        foreach ($permissionNames as $name) {
            Permission::firstOrCreate(
                ['name' => $name, 'guard_name' => 'web'],
                ['label' => $name, 'module' => 'system']
            );
        }

        $companyRole = Role::firstOrCreate(
            ['name' => 'company', 'guard_name' => 'web'],
            [
                'label' => 'Company',
                'description' => 'Company has access to manage business',
            ]
        );

        $companyRole->syncPermissions(
            Permission::whereIn('name', $permissionNames)->where('guard_name', 'web')->get()
        );

        $company->syncRoles([$companyRole]);

        $updates = ['type' => 'company'];
        if (strtolower((string) $company->email) !== strtolower(self::COMPANY_ADMIN_EMAIL)) {
            $updates['email'] = self::COMPANY_ADMIN_EMAIL;
        }
        if (! $company->is_active) {
            $updates['is_active'] = 1;
        }
        $company->update($updates);

        app(PermissionRegistrar::class)->forgetCachedPermissions();

        return [
            'permissions' => count($permissionNames),
            'email' => $company->fresh()->email,
        ];
    }

    /**
     * All permissions the territory company admin should hold.
     *
     * @return list<string>
     */
    public function companyPermissionNames(): array
    {
        if (! isSaas()) {
            return Permission::query()
                ->where('guard_name', 'web')
                ->pluck('name')
                ->all();
        }

        $seeder = new RoleSeeder;
        $method = (new ReflectionClass(RoleSeeder::class))->getMethod('getCompanyPermissions');
        $method->setAccessible(true);

        /** @var list<string> $names */
        $names = $method->invoke($seeder);

        $missing = Permission::query()
            ->where('guard_name', 'web')
            ->whereNotIn('name', $names)
            ->pluck('name')
            ->all();

        return array_values(array_unique(array_merge($names, $missing)));
    }

    private function resolveCompanyUser(): User
    {
        $company = User::where('slug', self::COMPANY_SLUG)->where('type', 'company')->first();

        if (! $company) {
            $company = User::where('slug', self::COMPANY_SLUG)->first();
        }

        if (! $company) {
            throw new \RuntimeException('Malawi Territory company user not found.');
        }

        return $company;
    }
}
