<?php

namespace App\Http\Controllers\Admin\School;

use App\Http\Controllers\Admin\PageController;
use App\Models\Staff;
use App\Services\School\StaffNumberGenerator;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class StaffController extends PageController
{
    public function __construct(
        private readonly StaffNumberGenerator $staffNumbers,
    ) {}

    public function index(): View
    {
        $staff = Staff::query()
            ->orderBy('last_name')
            ->paginate(25);

        return $this->page('admin.staff.index', [
            'crumbTitle' => 'Staff',
            'crumbSub' => 'Staff directory',
            'staff' => $staff,
            'canViewSalary' => $this->canViewSalary(),
        ]);
    }

    public function create(): View
    {
        return $this->page('admin.staff.create', [
            'crumbTitle' => 'Staff',
            'crumbSub' => 'New staff member',
            'canViewSalary' => $this->canViewSalary(),
            'suggestedStaffNumber' => $this->staffNumbers->generate(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $this->validateStaff($request);

        if (empty($validated['staff_number'])) {
            $validated['staff_number'] = $this->staffNumbers->generate();
        }

        if (! $this->canViewSalary()) {
            unset($validated['salary']);
        }

        $member = Staff::query()->create($validated);

        return redirect()
            ->route('school.staff.edit', $member)
            ->with('success', 'Staff member created successfully.');
    }

    public function show(Staff $staff): View
    {
        return $this->page('admin.staff.show', [
            'crumbTitle' => 'Staff',
            'crumbSub' => $staff->staff_number,
            'staffMember' => $staff,
            'canViewSalary' => $this->canViewSalary(),
        ]);
    }

    public function edit(Staff $staff): View
    {
        return $this->page('admin.staff.edit', [
            'crumbTitle' => 'Staff',
            'crumbSub' => 'Edit '.$staff->staff_number,
            'staffMember' => $staff,
            'canViewSalary' => $this->canViewSalary(),
        ]);
    }

    public function update(Request $request, Staff $staff): RedirectResponse
    {
        $validated = $this->validateStaff($request, $staff);

        if (! $this->canViewSalary()) {
            unset($validated['salary']);
        }

        $staff->update($validated);

        return redirect()
            ->route('school.staff.edit', $staff)
            ->with('success', 'Staff member updated successfully.');
    }

    public function destroy(Staff $staff): RedirectResponse
    {
        $staff->delete();

        return $this->redirectWithSuccess('school.staff.index', 'Staff member removed.');
    }

    private function canViewSalary(): bool
    {
        return auth()->user()?->can('finance.view') ?? false;
    }

    /**
     * @return array<string, mixed>
     */
    private function validateStaff(Request $request, ?Staff $staff = null): array
    {
        $rules = [
            'staff_number' => [
                'nullable',
                'string',
                'max:50',
                Rule::unique('staff', 'staff_number')->ignore($staff?->id),
            ],
            'first_name' => ['required', 'string', 'max:100'],
            'last_name' => ['required', 'string', 'max:100'],
            'other_names' => ['nullable', 'string', 'max:100'],
            'email' => [
                'nullable',
                'email',
                'max:255',
                Rule::unique('staff', 'email')->ignore($staff?->id),
            ],
            'phone' => ['nullable', 'string', 'max:30'],
            'job_title' => ['nullable', 'string', 'max:100'],
            'department' => ['nullable', 'string', 'max:100'],
            'hire_date' => ['nullable', 'date'],
            'status' => ['nullable', 'string', 'max:30'],
        ];

        if ($this->canViewSalary()) {
            $rules['salary'] = ['nullable', 'numeric', 'min:0'];
        }

        return $request->validate($rules);
    }
}
