<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Http\Requests\Employee\StoreEmployeeRequest;
use App\Http\Requests\Employee\UpdateEmployeeRequest;
use App\Models\Department;
use App\Models\Designation;
use App\Models\Document;
use App\Models\Company;
use App\Models\Location;
use App\Models\SalaryRevision;
use App\Models\SalaryGroup;
use App\Models\Role;
use App\Models\Shift;
use App\Models\User;
use App\Services\AuditService;
use App\Services\Documents\EmployeeDocumentComplianceService;
use App\Services\Payroll\SalaryStructureResolver;
use App\Services\Payroll\EmployeePayrollCalculator;
use App\Services\Payroll\PayrollRunService;
use App\Services\PlanPricingService;
use App\Services\SalaryRevisionService;
use App\Services\TenantRoleService;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Throwable;

class EmployeeController extends Controller
{
    public function __construct(
        protected PayrollRunService $payrollRunService,
        protected SalaryRevisionService $salaryRevisionService,
        protected EmployeePayrollCalculator $employeePayrollCalculator,
        protected EmployeeDocumentComplianceService $documentCompliance,
        protected AuditService $audit,
    ) {}

    public function index(Request $request)
    {
        $companyId = Auth::user()?->company_id;
        $query = User::with(['department', 'designation', 'reportingManager'])
            ->forTenantDirectory();
        if ($companyId) {
            $query->where('company_id', $companyId);
        }

        if ($request->filled('search')) {
            $query->where(function ($q) use ($request) {
                $q->where('name', 'like', '%' . $request->search . '%')
                    ->orWhere('employee_number', 'like', '%' . $request->search . '%')
                    ->orWhere('email', 'like', '%' . $request->search . '%');
            });
        }
        if ($request->filled('department_id')) {
            $query->where('department_id', $request->department_id);
        }
        if ($request->filled('designation_id')) {
            $query->where('designation_id', $request->designation_id);
        }
        $statusFilter = $this->applyEmployeeStatusFilter($query, $request);

        $employees = $query->orderBy('name')->paginate(16)->withQueryString();
        $employeeIds = collect($employees->items())->pluck('id')->map(fn ($id) => (int) $id)->all();
        $documentsByUser = $companyId
            ? $this->documentCompliance->documentsGroupedByUserId((int) $companyId, $employeeIds)
            : collect();
        $documentComplianceMap = [];
        foreach ($employees->items() as $emp) {
            $documentComplianceMap[$emp->id] = $this->documentCompliance->buildCompliance(
                $documentsByUser->get($emp->id, new EloquentCollection())
            );
        }
        $departments = Department::orderBy('name')->get();
        $designations = Designation::orderBy('name')->get();

        return view('employees.index', compact('employees', 'departments', 'designations', 'documentComplianceMap', 'statusFilter'));
    }

    public function export(Request $request): StreamedResponse
    {
        $companyId = Auth::user()?->company_id;
        $query = User::with(['department', 'designation', 'reportingManager'])
            ->forTenantDirectory();

        if ($companyId) {
            $query->where('company_id', $companyId);
        }

        if ($request->filled('search')) {
            $query->where(function ($q) use ($request) {
                $q->where('name', 'like', '%' . $request->search . '%')
                    ->orWhere('employee_number', 'like', '%' . $request->search . '%')
                    ->orWhere('email', 'like', '%' . $request->search . '%');
            });
        }
        if ($request->filled('department_id')) {
            $query->where('department_id', $request->department_id);
        }
        if ($request->filled('designation_id')) {
            $query->where('designation_id', $request->designation_id);
        }
        $this->applyEmployeeStatusFilter($query, $request);

        $employees = $query->orderBy('name')->get();
        $fileName = 'employees-' . now()->format('Ymd-His') . '.csv';

        return response()->streamDownload(function () use ($employees) {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, ['Employee ID', 'Name', 'Email', 'Department', 'Designation', 'Manager', 'Status']);

            foreach ($employees as $emp) {
                fputcsv($handle, [
                    $emp->employee_number ?? '',
                    $emp->name ?? '',
                    $emp->email ?? '',
                    $emp->department?->name ?? '',
                    $emp->designation?->name ?? '',
                    $emp->reportingManager?->name ?? '',
                    $emp->status ?? '',
                ]);
            }

            fclose($handle);
        }, $fileName, ['Content-Type' => 'text/csv']);
    }

    public function create()
    {
        $companyId = Auth::user()?->company_id;
        $company = $companyId ? Company::with('subscriptionPlan')->find($companyId) : null;
        if ($company && ! $company->canAddEmployees(1)) {
            return redirect()
                ->route('employees.index')
                ->with('error', $this->seatLimitReachedMessage($company))
                ->with('subscription_upgrade_url', route('subscription.request'));
        }

        $departments = Department::orderBy('name')->get();
        $designations = Designation::orderBy('name')->get();
        $locations = Location::orderBy('name')->get();
        $shifts = Shift::active()->orderBy('name')->get();
        $salaryGroupsQuery = SalaryGroup::query();
        if ($companyId) {
            $salaryGroupsQuery->where('company_id', $companyId);
        }
        $salaryGroups = $salaryGroupsQuery->orderBy('name')->get();
        $managersQuery = User::forActiveDirectory();
        if ($companyId) {
            $managersQuery->where('company_id', $companyId);
        }
        $managers = $managersQuery->orderBy('name')->get();
        $roles = Role::query()->orderBy('name')->get();
        return view('employees.create', compact('departments', 'designations', 'locations', 'shifts', 'salaryGroups', 'managers', 'roles'));
    }

    public function store(StoreEmployeeRequest $request)
    {
        $companyId = Auth::user()?->company_id;
        $company = $companyId ? Company::with('subscriptionPlan')->find($companyId) : null;
        if ($company && ! $company->canAddEmployees(1)) {
            return redirect()->back()
                ->withInput()
                ->with('error', $this->seatLimitReachedMessage($company))
                ->with('subscription_upgrade_url', route('subscription.request'));
        }

        $validated = $request->validated();
        $roleId = null;
        if (Auth::user()->hasPermission('users_edit') && ! empty($validated['role_id'])) {
            $roleId = (int) $validated['role_id'];
        } elseif ($companyId) {
            $roleId = TenantRoleService::ensureEmployeeRoleForCompany((int) $companyId)->id;
        }
        unset($validated['role_id']);
        $manualEmployeeNumber = trim((string) ($validated['employee_number'] ?? ''));
        $validated['employee_number'] = $manualEmployeeNumber !== '' ? $manualEmployeeNumber : null;
        // password cast is "hashed" — pass plain text
        $initialAnnualCtc = (float) ($validated['annual_ctc'] ?? 0);
        unset($validated['annual_ctc']);
        $employee = DB::transaction(function () use ($companyId, $validated, $roleId) {
            $payload = $validated;

            if (empty($payload['employee_number'])) {
                $payload['employee_number'] = $this->nextEmployeeNumber($companyId);
            }

            $user = new User;
            $user->fill($payload);
            $user->forceFill([
                'company_id' => $companyId,
                'user_type' => User::USER_TYPE_STAFF,
                'status' => 'active',
                'role_id' => $roleId,
                'allow_login' => true,
                'is_superadmin' => false,
            ])->save();

            return $user;
        });
        if ($initialAnnualCtc > 0 && !empty($employee->id) && !empty($employee->salary_group_id)) {
            $this->salaryRevisionService->createSalaryRevision((int)$companyId, $employee->id, $employee->salary_group_id, $initialAnnualCtc);
        }
        $this->audit->log('employee.created', $employee, ['email' => $employee->email]);
        return redirect()->route('employees.show', $employee->id)->with('success', 'Employee created successfully.');
    }

    public function show(int $employee)
    {
        $viewer = Auth::user();
        $companyId = Auth::user()?->company_id;
        $canViewCompensation = (bool) ($viewer?->hasPermission('payrolls_view'));
        $query = User::with(['department', 'designation', 'location', 'shift', 'salaryGroup.salaryGroupComponents.salaryComponent', 'reportingManager'])
            ->forTenantDirectory();
        if ($companyId) {
            $query->where('company_id', $companyId);
        }
        $employee = $query->findOrFail($employee);
        $canViewFullEmployeeProfile = (bool) ($viewer?->canViewFullEmployeeProfile($employee));
        $attendances = $employee->attendances()->orderByDesc('date')->limit(30)->get();
        $leaves = $employee->leaves()->with('leaveType')->orderByDesc('start_date')->limit(20)->get();
        $payrolls = $canViewCompensation
            ? \App\Models\EmployeePayroll::withoutGlobalScopes()
                ->where('company_id', $employee->company_id)
                ->where('user_id', $employee->id)
                ->with('payrollCycle')
                ->orderByDesc('id')
                ->limit(24)
                ->get()
            : collect();
        $documents = $this->documentCompliance
            ->documentsForUser((int) $employee->company_id, (int) $employee->id)
            ->sortByDesc('created_at')
            ->values();
        $uploadCategories = $this->getUploadCategories();
        $documentCompliance = $this->documentCompliance->buildCompliance($documents);
        $assets = \App\Models\Asset::where('assigned_to', $employee->id)->with('assetType')->get();
        $latestRevision = SalaryRevision::withoutGlobalScopes()
            ->where('user_id', $employee->id)
            ->when($companyId, fn ($q) => $q->where('company_id', $companyId))
            ->orderByDesc('effective_date')
            ->orderByDesc('id')
            ->first();
        $salaryStructure = $canViewCompensation
            ? $this->buildSalaryStructureForEmployee($employee, $latestRevision)
            : ['rows' => [], 'monthly_total' => 0, 'annual_total' => 0, 'effective_date' => null, 'source' => 'none'];
        $salaryBreakup = null;
        if ($companyId && $canViewCompensation) {
            $settings = $this->payrollRunService->getStatutorySettings((int) $companyId);
            $ptByState = $this->payrollRunService->getPtSlabsByState((int) $companyId, now());
            $ptSlabs = $ptByState[$employee->work_state ?? ''] ?? [];
            $salaryBreakup = $this->employeePayrollCalculator->indicativeBreakdown(
                $employee,
                (int) $companyId,
                now(),
                $settings,
                $ptSlabs
            );
        }
        $salaryGroups = $canViewCompensation
            ? SalaryGroup::query()
                ->when($companyId, fn ($q) => $q->where('company_id', $companyId))
                ->with('salaryGroupComponents.salaryComponent')
                ->orderBy('name')
                ->get()
            : collect();

        return view('employees.show', compact('employee', 'attendances', 'leaves', 'payrolls', 'documents', 'assets', 'uploadCategories', 'documentCompliance', 'salaryStructure', 'salaryBreakup', 'latestRevision', 'salaryGroups', 'canViewCompensation', 'canViewFullEmployeeProfile'));
    }

    public function salaryBreakup($salaryRevisionId)
    {
        $user = auth()->user();
        $companyId = (int) $user->company_id;

        $revision = SalaryRevision::withoutGlobalScopes()
            ->where('id', $salaryRevisionId)
            ->where('company_id', $companyId)
            ->firstOrFail();

        if ((int) $revision->user_id !== (int) $user->id && ! $user->hasPermission('payrolls_view')) {
            abort(403, 'You do not have permission to view this salary breakup.');
        }

        $employee = (int) $revision->user_id === (int) $user->id
            ? $user
            : User::withoutGlobalScopes()
                ->where('company_id', $companyId)
                ->findOrFail($revision->user_id);

        $settings = $this->payrollRunService->getStatutorySettings($companyId);
        $ptByState = $this->payrollRunService->getPtSlabsByState($companyId, now());
        $ptSlabs = $ptByState[$employee->work_state ?? ''] ?? [];
        $salaryBreakup = $this->employeePayrollCalculator->indicativeBreakdown(
            $employee,
            $companyId,
            now(),
            $settings,
            $ptSlabs,
            (int) $salaryRevisionId
        );

        return view('employees.salary-breakup', compact('employee', 'salaryBreakup'));
    }

    public function storeSalaryRevision(Request $request, int $employee)
    {
        $companyId = Auth::user()?->company_id;

        $validated = $request->validate([
            'effective_date' => 'required|date',
            'ctc_annual' => 'required|numeric|min:0',
            'salary_group' => [
                'required',
                Rule::exists('salary_groups', 'id')->when($companyId, fn ($rule) => $rule->where('company_id', $companyId)),
            ],
        ]);

        $employeeRow = User::query()
            ->with(['salaryGroup.salaryGroupComponents.salaryComponent'])
            ->forTenantDirectory()
            ->where('id', $employee)
            ->when($companyId, fn ($q) => $q->where('company_id', $companyId))
            ->firstOrFail();

        $initialAnnualCtc = (float) $validated['ctc_annual'];
        $salary_group_id = $request->input('salary_group');
        $effective_date = $validated['effective_date'];

        $employeeRow->update([
            'salary_group_id' => $salary_group_id,
        ]);

        $this->salaryRevisionService->createSalaryRevision((int)$companyId, $employeeRow->id, $employeeRow->salary_group_id, $initialAnnualCtc, $effective_date);

        return redirect()->route('employees.show', $employeeRow->id)->with('success', 'Salary revision saved successfully.');
    }

    public function edit(int $employee)
    {
        $companyId = Auth::user()?->company_id;
        $query = User::forTenantDirectory();
        if ($companyId) {
            $query->where('company_id', $companyId);
        }
        $employee = $query->findOrFail($employee);
        $departments = Department::orderBy('name')->get();
        $designations = Designation::orderBy('name')->get();
        $locations = Location::orderBy('name')->get();
        $shifts = Shift::active()->orderBy('name')->get();
        $salaryGroupsQuery = SalaryGroup::query();
        if ($companyId) {
            $salaryGroupsQuery->where('company_id', $companyId);
        }
        $salaryGroups = $salaryGroupsQuery->orderBy('name')->get();
        $managersQuery = User::forActiveDirectory()->where('id', '!=', $employee->id);
        if ($companyId) {
            $managersQuery->where('company_id', $companyId);
        }
        $managers = $managersQuery->orderBy('name')->get();
        $roles = Role::query()->orderBy('name')->get();
        $canFullyManageEmployee = $this->canFullyManageEmployee(Auth::user());

        return view('employees.edit', compact('employee', 'departments', 'designations', 'locations', 'shifts', 'salaryGroups', 'managers', 'roles', 'canFullyManageEmployee'));
    }

    public function update(UpdateEmployeeRequest $request, int $employee)
    {
        $companyId = Auth::user()?->company_id;
        $query = User::forTenantDirectory();
        if ($companyId) {
            $query->where('company_id', $companyId);
        }
        $employee = $query->findOrFail($employee);
        $oldSalaryGroupId = $employee->salary_group_id;
        $validated = $request->validated();
        if (! Auth::user()->hasPermission('users_edit')) {
            unset($validated['role_id']);
        }
        if (! $this->canFullyManageEmployee(Auth::user())) {
            unset($validated['allow_login'], $validated['employee_number']);
        } else {
            $validated['allow_login'] = $request->boolean('allow_login');

            $manualEmployeeNumber = trim((string) ($validated['employee_number'] ?? ''));
            if ($manualEmployeeNumber === '') {
                $manualEmployeeNumber = $this->nextEmployeeNumber($companyId);
            }
            $validated['employee_number'] = $manualEmployeeNumber ?: null;
        }

        if (! empty($validated['password'])) {
            // password cast hashes — keep plain text
        } else {
            unset($validated['password']);
        }
        $initialAnnualCtc = (float) ($validated['annual_ctc'] ?? 0);
        unset($validated['annual_ctc']);

        $privileged = [];
        foreach (['status', 'role_id', 'allow_login'] as $key) {
            if (array_key_exists($key, $validated)) {
                $privileged[$key] = $validated[$key];
                unset($validated[$key]);
            }
        }

        $reactivating = isset($privileged['status'])
            && $privileged['status'] === User::STATUS_ACTIVE
            && $employee->status !== User::STATUS_ACTIVE;
        if ($reactivating && $companyId) {
            $company = Company::with('subscriptionPlan')->find($companyId);
            if ($company && ! $company->canAddEmployees(1)) {
                return redirect()->back()
                    ->withInput()
                    ->with('error', $this->seatLimitReachedMessage($company))
                    ->with('subscription_upgrade_url', route('subscription.request'));
            }
        }

        $employee->fill($validated);
        if ($privileged !== []) {
            $employee->forceFill($privileged);
        }
        $employee->save();
        
        $salaryGroupChanged = isset($validated['salary_group_id']) && $validated['salary_group_id'] != $oldSalaryGroupId;
        
        if (!empty($employee->salary_group_id)) {
            if ($initialAnnualCtc > 0) {
                $ctcToUse = $initialAnnualCtc;
            } elseif ($salaryGroupChanged && $employee->latestEffectiveSalaryRevision()) {
                $ctcToUse = $employee->latestEffectiveSalaryRevision()->ctc_annual;
            } else {
                $ctcToUse = null;
            }

            if ($ctcToUse !== null) {
                $this->salaryRevisionService->createSalaryRevision((int)$companyId, $employee->id, $employee->salary_group_id, $ctcToUse);
            }
        }

        $this->audit->log('employee.updated', $employee->fresh(), ['email' => $employee->email]);

        return redirect()->route('employees.show', $employee->id)->with('success', 'Employee updated successfully.');
    }

    public function destroy(int $employee)
    {
        $companyId = Auth::user()?->company_id;
        $query = User::forTenantDirectory();
        if ($companyId) {
            $query->where('company_id', $companyId);
        }
        $employee = $query->findOrFail($employee);
        $this->audit->log('employee.deleted', $employee, ['email' => $employee->email]);
        $employee->delete();
        return redirect()->route('employees.index')->with('success', 'Employee removed successfully.');
    }

    public function storeDocument(Request $request, int $employee)
    {
        $viewer = Auth::user();
        $companyId = $viewer?->company_id;
        $query = User::forTenantDirectory();
        if ($companyId) {
            $query->where('company_id', $companyId);
        }
        $employee = $query->findOrFail($employee);
        abort_unless($viewer && $viewer->canViewFullEmployeeProfile($employee), 403, 'You cannot upload documents for this employee.');
        $uploadCategories = $this->getUploadCategories();
        $validated = $request->validate([
            'type' => ['required', 'string', 'max:50', Rule::in(array_keys($uploadCategories))],
            'document' => 'required|file|max:10240|mimes:pdf,doc,docx,xls,xlsx,txt,png,jpg,jpeg',
        ]);
        $file = $request->file('document');
        $path = $file->store('documents/' . ($companyId ?? 'shared'), 'local');
        $categoryLabel = $uploadCategories[$validated['type']] ?? ucfirst(str_replace('_', ' ', $validated['type']));
        $employeeRef = $employee->employee_number ?: ('EMP' . $employee->id);
        $generatedName = $categoryLabel . ' - ' . $employeeRef . ' - ' . now()->format('YmdHis');
        Document::create([
            'company_id' => $companyId,
            'name' => $generatedName,
            'type' => $validated['type'],
            'category' => $validated['type'],
            'path' => $path,
            'documentable_type' => User::class,
            'documentable_id' => $employee->id,
            'uploaded_by' => Auth::id(),
        ]);
        return redirect()->route('employees.show', $employee->id)->with('success', 'Document uploaded.');
    }

    /**
     * @return array<string, string>
     */
    private function getUploadCategories(): array
    {
        return config('employee_documents.upload_categories', []);
    }

    /**
     * @return array{
     *   rows: array<int, array{name:string, monthly:float, annual:float, type:string}>,
     *   monthly_total: float,
     *   annual_total: float,
     *   effective_date: ?string,
     *   source: string
     * }
     */
    private function buildSalaryStructureForEmployee(User $employee, ?SalaryRevision $revision = null): array
    {
        $salaryGroup = $employee->salaryGroup;
        $rows = [];

        if ($revision && is_array($revision->components_json) && ! empty($revision->components_json)) {
            foreach ($this->sanitizeRevisionComponents($revision->components_json) as $component) {
                $annual = round(max(0, (float) ($component['annual'] ?? 0)), 2);
                $rows[] = [
                    'name' => (string) ($component['name'] ?? 'Component'),
                    'monthly' => round($annual / 12, 2),
                    'annual' => $annual,
                    'type' => 'earning',
                ];
            }
            $monthlyTotal = round(array_sum(array_map(fn ($row) => (float) $row['monthly'], $rows)), 2);
            $annualTotal = round(array_sum(array_map(fn ($row) => (float) $row['annual'], $rows)), 2);
            return [
                'rows' => $rows,
                'monthly_total' => $monthlyTotal,
                'annual_total' => $annualTotal,
                'effective_date' => $revision->effective_date?->format('M j, Y'),
                'source' => 'revision',
            ];
        }

        if ($salaryGroup && $salaryGroup->relationLoaded('salaryGroupComponents') && $salaryGroup->salaryGroupComponents->isNotEmpty()) {
            $resolvedComponents = app(SalaryStructureResolver::class)
                ->resolveMonthlyComponents($employee, (int) (Auth::user()?->company_id ?? 0), now());
            foreach ($resolvedComponents as $component) {
                $monthly = (float) ($component['amount'] ?? 0);
                $rows[] = [
                    'name' => (string) ($component['name'] ?? 'Component'),
                    'monthly' => round(max(0, $monthly), 2),
                    'annual' => round(max(0, $monthly) * 12, 2),
                    'type' => (string) ($component['type'] ?? 'other'),
                ];
            }

            $effectiveDate = $salaryGroup->updated_at ?? $employee->updated_at ?? $employee->joining_date;
            $source = 'salary_group';
        } else {
            $effectiveDate = null;
            $source = 'none';
        }

        $monthlyTotal = round(array_sum(array_map(fn ($row) => (float) $row['monthly'], $rows)), 2);
        $annualTotal = round(array_sum(array_map(fn ($row) => (float) $row['annual'], $rows)), 2);

        return [
            'rows' => $rows,
            'monthly_total' => $monthlyTotal,
            'annual_total' => $annualTotal,
            'effective_date' => $effectiveDate ? $effectiveDate->format('M j, Y') : null,
            'source' => $source,
        ];
    }

    private function nextEmployeeNumber(?int $companyId): string
    {
        if (! $companyId) {
            return '' . str_pad('1', 5, '0', STR_PAD_LEFT);
        }

        $sequence = DB::table('employee_number_sequences')
            ->where('company_id', $companyId)
            ->lockForUpdate()
            ->first();

        if (! $sequence) {
            DB::table('employee_number_sequences')->insert([
                'company_id' => $companyId,
                'prefix' => null,
                'digits' => 1,
                'last_number' => 1,
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            return '' . str_pad('1', 5, '0', STR_PAD_LEFT);
        }

        $prefix = strtoupper(trim((string) ($sequence->prefix ?? null)));

        $digits = max(1, min(10, (int) ($sequence->digits ?? 5)));
        $nextNumber = (int) $sequence->last_number + 1;

        DB::table('employee_number_sequences')
            ->where('company_id', $companyId)
            ->update([
                'last_number' => $nextNumber,
                'prefix' => $prefix,
                'digits' => $digits,
                'updated_at' => now(),
            ]);

        return $prefix . str_pad((string) $nextNumber, $digits, '0', STR_PAD_LEFT);
    }

    /**
     * @param mixed $components
     * @return array<int, array{name:string, annual:float}>
     */
    private function sanitizeRevisionComponents($components): array
    {
        if (!is_array($components)) {
            return [];
        }
        $rows = [];
        foreach ($components as $component) {
            if (!is_array($component)) {
                continue;
            }
            $name = trim((string) ($component['name'] ?? ''));
            if ($name === '') {
                continue;
            }
            $annual = round(max(0, (float) ($component['annual'] ?? 0)), 2);
            $monthly = isset($component['monthly']) ? round(max(0, (float) $component['monthly']), 2) : round($annual / 12, 2);
            $rows[] = [
                'name'       => $name,
                'type'       => (string) ($component['type'] ?? 'earning'),
                'value'      => round(max(0, (float) ($component['value'] ?? 0)), 2),
                'value_type' => (string) ($component['value_type'] ?? 'fixed'),
                'annual'     => $annual,
                'monthly'    => $monthly,
            ];
        }
        return $rows;
    }

    /**
     * Default employee list to active only; explicit empty status = all.
     *
     * @param  \Illuminate\Database\Eloquent\Builder<User>  $query
     */
    protected function applyEmployeeStatusFilter($query, Request $request): string
    {
        $status = $request->has('status')
            ? (string) $request->input('status', '')
            : User::STATUS_ACTIVE;

        if ($status !== '' && $status !== 'all') {
            $query->where('status', $status);
        }

        return $status === '' ? 'all' : $status;
    }

    protected function canFullyManageEmployee(?User $authUser): bool
    {
        if (! $authUser) {
            return false;
        }

        return $authUser->hasPermission('users_edit')
            && ($authUser->isTenantAdmin() || $authUser->isTenantHr() || $authUser->isCompanyAccountAdmin());
    }

    protected function seatLimitReachedMessage(Company $company): string
    {
        $pricing = app(PlanPricingService::class);
        $next = $pricing->suggestNextPlan($company);
        $upgradeHint = '';
        if ($next) {
            $quote = $pricing->canUpgradeTo($company, $next)
                ? $pricing->calculateUpgradeQuote($company, $next)
                : $pricing->calculateYearlyTotal($next, null, $company);
            $upgradeHint = ' Suggested: '.$next->name.' for ₹'.number_format($quote['total'], 2).'.';
        }

        return 'Employee seat limit reached for your plan ('.$company->employeeSeatLimit().').'.$upgradeHint.' Manage subscription to upgrade.';
    }
}
