<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\AuditLogService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Inertia\Response;
use Spatie\Permission\Models\Role;

class StaffManagementController extends Controller
{
    private const STAFF_ROLES = ['support', 'admin', 'super-admin'];

    public function index(): Response
    {
        $staff = User::query()
            ->with('roles:id,name')
            ->whereHas('roles', fn ($q) => $q->whereIn('name', self::STAFF_ROLES))
            ->latest('id')
            ->paginate(20)
            ->withQueryString()
            ->through(function (User $user) {
                return [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'status' => $user->status ?? 'active',
                    'roles' => $user->roles->pluck('name')->values(),
                    'created_at' => optional($user->created_at)->toDateTimeString(),
                ];
            });

        $roles = Role::query()
            ->whereIn('name', self::STAFF_ROLES)
            ->orderBy('name')
            ->get(['name'])
            ->pluck('name')
            ->values();

        return Inertia::render('Admin/Staff/Index', [
            'staff' => $staff,
            'roles' => $roles,
        ]);
    }

    public function store(Request $request, AuditLogService $auditLogService): RedirectResponse
    {
        $actor = $request->user();

        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255', 'unique:users,email'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'role' => ['required', Rule::in(self::STAFF_ROLES)],
            'status' => ['required', Rule::in(User::STATUSES)],
            'action_reason' => ['required', 'string', 'max:255'],
            'current_password' => ['required', 'current_password'],
        ]);

        if ($data['role'] === 'super-admin' && ! $actor->hasRole('super-admin')) {
            abort(403);
        }

        $staff = User::query()->create([
            'name' => $data['name'],
            'email' => Str::lower($data['email']),
            'password' => $data['password'],
            'status' => $data['status'],
            'customer_tier' => 'subscriber',
        ]);

        $staff->syncRoles([$data['role']]);

        $auditLogService->log(
            admin: $actor,
            action: 'admin.staff.created',
            entity: $staff,
            oldValues: null,
            newValues: [
                'name' => $staff->name,
                'email' => $staff->email,
                'status' => $staff->status,
                'roles' => $staff->getRoleNames()->values()->all(),
                'reason' => $data['action_reason'],
            ],
            ipAddress: $request->ip(),
            userAgent: $request->userAgent(),
        );

        return back()->with('success', 'Staff account created.');
    }

    public function update(Request $request, User $user, AuditLogService $auditLogService): RedirectResponse
    {
        $actor = $request->user();

        abort_unless($user->hasAnyRole(self::STAFF_ROLES), 404);

        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')->ignore($user->id)],
            'role' => ['required', Rule::in(self::STAFF_ROLES)],
            'status' => ['required', Rule::in(User::STATUSES)],
            'password' => ['nullable', 'string', 'min:8', 'confirmed'],
            'action_reason' => ['required', 'string', 'max:255'],
            'current_password' => ['required', 'current_password'],
        ]);

        if ($user->id === $actor->id && ! $user->hasRole($data['role'])) {
            return back()->withErrors(['role' => 'You cannot change your own role from Staff Management.']);
        }

        if ($data['role'] === 'super-admin' && ! $actor->hasRole('super-admin')) {
            abort(403);
        }

        $old = [
            'name' => $user->name,
            'email' => $user->email,
            'status' => $user->status,
            'roles' => $user->getRoleNames()->values()->all(),
        ];

        $user->fill([
            'name' => $data['name'],
            'email' => Str::lower($data['email']),
            'status' => $data['status'],
        ]);

        if (filled($data['password'] ?? null)) {
            $user->password = $data['password'];
        }

        $user->save();
        $user->syncRoles([$data['role']]);

        $auditLogService->log(
            admin: $actor,
            action: 'admin.staff.updated',
            entity: $user,
            oldValues: $old,
            newValues: [
                'name' => $user->name,
                'email' => $user->email,
                'status' => $user->status,
                'roles' => $user->getRoleNames()->values()->all(),
                'reason' => $data['action_reason'],
            ],
            ipAddress: $request->ip(),
            userAgent: $request->userAgent(),
        );

        return back()->with('success', 'Staff account updated.');
    }
}
