<?php

namespace App\Console\Commands;

use App\Models\Company;
use App\Models\Role;
use App\Models\User;
use App\Services\TenantRoleService;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class ResetTenantPermissions extends Command
{
    protected $signature = 'hrms:reset-permissions {--company_id=* : Limit to specific company IDs} {--assign_role=employee : Role name to assign to users with no role_id (admin, hr, manager, employee)} {--dry-run : Show what would change without writing}';

    protected $description = 'Reset tenant roles/permissions and ensure all users have a valid role_id.';

    public function handle(): int
    {
        $dryRun = (bool) $this->option('dry-run');
        $assignRole = strtolower((string) $this->option('assign_role'));
        $companyIds = (array) $this->option('company_id');

        (new RolePermissionSeeder())->run();

        $companiesQuery = Company::query();
        if (! empty($companyIds)) {
            $companiesQuery->whereIn('id', array_map('intval', $companyIds));
        }
        $companies = $companiesQuery->get();

        if ($companies->isEmpty()) {
            $this->warn('No companies matched.');
            return self::SUCCESS;
        }

        foreach ($companies as $company) {
            $this->info('Company #'.$company->id.' '.($company->name ?? ''));

            try {
                $roles = TenantRoleService::syncAllDefaultRolesForCompany((int) $company->id, $dryRun);
            } catch (\Throwable $e) {
                $this->error($e->getMessage());

                return self::FAILURE;
            }

            if ($dryRun) {
                $p = \App\Models\Permission::query()->pluck('id', 'name')->all();
                $nAdmin = count($p);
                $nHr = count(TenantRoleService::mapPermissionIds(TenantRoleService::hrPermissionNames(), $p));
                $nMgr = count(TenantRoleService::mapPermissionIds(TenantRoleService::managerPermissionNames(), $p));
                $nEmp = count(TenantRoleService::mapEmployeePermissionIds($p));
                $this->line("  Would sync permissions: admin={$nAdmin}, hr={$nHr}, manager={$nMgr}, employee={$nEmp}");
            }

            $usersQuery = User::withoutGlobalScopes()->where('company_id', $company->id)->where('is_superadmin', false);

            $missingRoleUsers = (clone $usersQuery)->whereNull('role_id')->count();
            $this->line('  Users with NULL role_id: '.$missingRoleUsers);

            if (! $dryRun && $missingRoleUsers > 0) {
                $role = match ($assignRole) {
                    'admin' => $roles['admin'],
                    'hr' => $roles['hr'],
                    'manager' => $roles['manager'],
                    default => $roles['employee'],
                };
                (clone $usersQuery)->whereNull('role_id')->update(['role_id' => $role->id]);
            }

            $invalidRoleUserIds = DB::table('users')
                ->where('company_id', $company->id)
                ->where('is_superadmin', 0)
                ->whereNotNull('role_id')
                ->whereNotIn('role_id', Role::withoutGlobalScopes()->where('company_id', $company->id)->pluck('id')->all())
                ->pluck('id')
                ->all();
            if (! empty($invalidRoleUserIds)) {
                $this->warn('  Users with invalid role_id: '.count($invalidRoleUserIds));
                if (! $dryRun) {
                    DB::table('users')->whereIn('id', $invalidRoleUserIds)->update(['role_id' => $roles['employee']->id]);
                }
            }
        }

        $this->info($dryRun ? 'Dry run complete.' : 'Reset complete.');

        return self::SUCCESS;
    }
}
