<?php

namespace App\Http\Controllers\Company\Admin;

use App\Http\Controllers\Controller;
use App\Models\{AuditLog, Role, User};
use Illuminate\Http\Request;
use Illuminate\Support\Facades\{DB, Hash};
use Illuminate\Validation\Rule;

class UsersController extends Controller
{
    public function index()
    {
        $this->gate('users', 'view');

        $users = User::with('roles')
            ->withTrashed()
            ->orderByDesc('is_admin')
            ->orderBy('name')
            ->paginate(25);

        return view('admin.users.index', compact('users'));
    }

    public function create()
    {
        $this->gate('users', 'create');
        $roles = Role::orderBy('name')->get();
        return view('admin.users.create', compact('roles'));
    }

    public function store(Request $request)
    {
        $this->gate('users', 'create');

        $companyId = auth()->user()->company_id;

        $validated = $request->validate([
            'name'                  => 'required|string|max:100',
            'username'              => [
                'required', 'string', 'max:50', 'regex:/^[a-z0-9_]+$/',
                Rule::unique('users')
                    ->where(fn($q) => $q->where('company_id', $companyId)->whereNull('deleted_at')),
            ],
            'email'                 => 'nullable|email|max:150',
            'phone'                 => 'nullable|string|max:30',
            'password'              => 'required|string|min:8|confirmed',
            'is_admin'              => 'boolean',
            'force_password_change' => 'boolean',
            'roles'                 => 'nullable|array',
            'roles.*'               => ['integer', Rule::exists('roles', 'id')
                                           ->where('company_id', $companyId)],
        ]);

        $user = User::create([
            'company_id'            => $companyId,
            'name'                  => $validated['name'],
            'username'              => strtolower($validated['username']),
            'email'                 => $validated['email'] ?? null,
            'phone'                 => $validated['phone'] ?? null,
            'password'              => Hash::make($validated['password']),
            'is_admin'              => $request->boolean('is_admin'),
            'is_active'             => true,
            'force_password_change' => $request->boolean('force_password_change', true),
        ]);

        if (!empty($validated['roles'])) {
            $user->roles()->sync($validated['roles']);
        }

        AuditLog::record('create', 'users', (string) $user->id, null,
            ['username' => $user->username, 'name' => $user->name],
            "User created: {$user->username}");

        return redirect()->route('admin.users.index')
            ->with('success', "User '{$user->name}' created successfully.");
    }

    public function edit(User $user)
    {
        $this->gate('users', 'edit');
        $this->sameCompany($user);

        $roles       = Role::orderBy('name')->get();
        $userRoleIds = $user->roles()->pluck('roles.id')->toArray();

        return view('admin.users.edit', compact('user', 'roles', 'userRoleIds'));
    }

    public function update(Request $request, User $user)
    {
        $this->gate('users', 'edit');
        $this->sameCompany($user);

        $companyId = auth()->user()->company_id;

        $validated = $request->validate([
            'name'      => 'required|string|max:100',
            'username'  => [
                'required', 'string', 'max:50', 'regex:/^[a-z0-9_]+$/',
                Rule::unique('users')
                    ->where(fn($q) => $q->where('company_id', $companyId)->whereNull('deleted_at'))
                    ->ignore($user->id),
            ],
            'email'     => 'nullable|email|max:150',
            'phone'     => 'nullable|string|max:30',
            'is_admin'  => 'boolean',
            'is_active' => 'boolean',
            'roles'     => 'nullable|array',
            'roles.*'   => ['integer', Rule::exists('roles', 'id')
                               ->where('company_id', $companyId)],
        ]);

        // Prevent deactivating or un-admining yourself
        if ($user->id === auth()->id()) {
            if (!$request->boolean('is_active')) {
                return back()->withErrors(['is_active' => 'You cannot deactivate your own account.']);
            }
        }

        $old = $user->only(['name','username','email','is_admin','is_active']);

        $user->update([
            'name'      => $validated['name'],
            'username'  => strtolower($validated['username']),
            'email'     => $validated['email'] ?? null,
            'phone'     => $validated['phone'] ?? null,
            'is_admin'  => $request->boolean('is_admin'),
            'is_active' => $request->boolean('is_active', true),
        ]);

        $user->roles()->sync($validated['roles'] ?? []);

        AuditLog::record('update', 'users', (string) $user->id, $old,
            $user->only(['name','username','email','is_admin','is_active']),
            "User updated: {$user->username}");

        return redirect()->route('admin.users.index')
            ->with('success', "User '{$user->name}' updated successfully.");
    }

    public function resetPassword(Request $request, User $user)
    {
        $this->gate('users', 'reset_password');
        $this->sameCompany($user);

        $request->validate([
            'new_password' => 'required|string|min:8|confirmed',
        ]);

        $user->update([
            'password'              => Hash::make($request->new_password),
            'force_password_change' => $request->boolean('force_password_change', true),
            'password_changed_at'   => null,
        ]);

        // Invalidate this user's active sessions so they must re-login with new password
        DB::table('company_sessions')
            ->where('user_id', $user->id)
            ->delete();

        AuditLog::record('password_reset', 'users', (string) $user->id,
            null, null, "Password reset for user: {$user->username}");

        return back()->with('success', "Password reset for '{$user->name}' successfully.");
    }

    public function toggleActive(User $user)
    {
        $this->gate('users', 'edit');
        $this->sameCompany($user);

        if ($user->id === auth()->id()) {
            return back()->withErrors(['error' => 'You cannot deactivate your own account.']);
        }

        $old = $user->is_active;
        $user->update(['is_active' => !$old]);

        // If deactivating, kill their sessions immediately
        if ($old) {
            DB::table('company_sessions')->where('user_id', $user->id)->delete();
        }

        AuditLog::record('status_change', 'users', (string) $user->id,
            ['is_active' => $old], ['is_active' => !$old],
            "User " . (!$old ? 'activated' : 'deactivated') . ": {$user->username}");

        return back()->with('success', "User " . (!$old ? 'activated' : 'deactivated') . " successfully.");
    }

    public function destroy(User $user)
    {
        $this->gate('users', 'edit');
        $this->sameCompany($user);

        if ($user->id === auth()->id()) {
            return back()->withErrors(['error' => 'You cannot delete your own account.']);
        }

        // Must always keep at least one admin
        if ($user->is_admin) {
            $adminCount = User::where('company_id', $user->company_id)
                ->where('is_admin', true)
                ->count();
            if ($adminCount <= 1) {
                return back()->withErrors(['error' => 'Cannot delete the last administrator account.']);
            }
        }

        $username = $user->username;

        // Kill their sessions before soft-deleting
        DB::table('company_sessions')->where('user_id', $user->id)->delete();

        $user->delete(); // soft delete

        AuditLog::record('delete', 'users', (string) $user->id,
            null, null, "User soft-deleted: {$username}");

        return redirect()->route('admin.users.index')
            ->with('success', "User '{$username}' deleted.");
    }

    // ── Helpers ───────────────────────────────────────────────────────────────
    private function gate(string $module, string $action): void
    {
        if (!auth()->user()->hasPermission($module, $action)) {
            abort(403, 'Insufficient permissions.');
        }
    }

    private function sameCompany(User $user): void
    {
        // Compare against unwrapped company_id to handle softDeleted users
        if ((int) $user->company_id !== (int) auth()->user()->company_id) {
            abort(403);
        }
    }
}
