<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
use Inertia\Inertia;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Hash;

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $perPage = $request->input('per_page', 10);
        $sortBy = $request->input('sort_by', 'id');
        $sortOrder = $request->input('sort_order', 'asc');
        $search = $request->input('search');
        $roleId = $request->input('role');

        $query = User::with(['roles:id,name,display_name']);

        // Handle Search
        if ($search) {
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('email', 'like', "%{$search}%")
                  ->orWhere('username', 'like', "%{$search}%");
            });
        }

        // Handle Role Filter
        if ($roleId && $roleId !== 'all') {
            $query->whereHas('roles', function ($q) use ($roleId) {
                $q->where('id', $roleId);
            });
        }

         // Handle sorting
        if (in_array($sortBy, ['name', 'created_at'])) {
           $query->orderBy($sortBy, $sortOrder);
        } else {
           $query->orderBy('id', 'asc');
        }

        $users = $query->paginate($perPage)->withQueryString();
        $roles = Role::select('id', 'name', 'display_name')->get();

        return Inertia::render('Admin/User/Index', [
            'users' => $users,
            'roles' => $roles,
            'filters' => $request->only(['per_page', 'sort_by', 'sort_order', 'search', 'role']),
        ]);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        $roles = Role::pluck('display_name', 'name');

        return Inertia::render('Admin/User/Create', [
            'roles' => $roles
        ]);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['nullable', 'string', 'email', 'max:255', 'unique:users'],
            'username' => ['required', 'string', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
            'roles' => ['array'], 
        ], [
            'password.required' => '請輸入密碼',
            'password.min' => '密碼長度至少需 :min 個字元',
            'password.confirmed' => '密碼確認不符',
        ]);

        $user = User::create([
            'name' => $validated['name'],
            'email' => $validated['email'],
            'username' => $validated['username'],
            'password' => Hash::make($validated['password']),
        ]);

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

            // Update the 'created' log to include roles
            $activity = \Spatie\Activitylog\Models\Activity::where('subject_type', get_class($user))
                ->where('subject_id', $user->id)
                ->where('event', 'created')
                ->latest()
                ->first();

            if ($activity) {
                $roleNames = $user->roles()->pluck('display_name')->join(', ');
                $properties = $activity->properties->toArray();
                $properties['attributes']['role_id'] = $roleNames;
                $activity->properties = $properties;
                $activity->save();
            }
        }

        return redirect()->route('users.index')->with('success', '使用者建立成功');
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id)
    {
        $user = User::with('roles')->findOrFail($id);
        $roles = Role::get(['id', 'name', 'display_name']); 

        return Inertia::render('Admin/User/Edit', [
            'user' => $user,
            'roles' => $roles,
            'currentRoles' => $user->getRoleNames()
        ]);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id)
    {
        $user = User::findOrFail($id);
        
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['nullable', 'string', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
            'username' => ['required', 'string', 'max:255', Rule::unique('users')->ignore($user->id)],
            'password' => ['nullable', 'string', 'min:8', 'confirmed'],
            'roles' => ['array'],
        ], [
            'password.min' => '密碼長度至少需 :min 個字元',
            'password.confirmed' => '密碼確認不符',
        ]);

        // 1. Prepare data and detect changes
        $userData = [
            'name' => $validated['name'],
            'email' => $validated['email'],
            'username' => $validated['username'],
        ];

        if (!empty($validated['password'])) {
            $userData['password'] = Hash::make($validated['password']);
        }

        $user->fill($userData);

        // Capture dirty attributes for manual logging
        $dirty = $user->getDirty();
        $oldAttributes = [];
        $newAttributes = [];

        foreach ($dirty as $key => $value) {
            $oldAttributes[$key] = $user->getOriginal($key);
            $newAttributes[$key] = $value;
        }

        // Save without triggering events (prevents duplicate log)
        $user->saveQuietly();

        // 2. Handle Roles
        $roleChanges = null;
        if (isset($validated['roles'])) {
            $oldRoles = $user->roles()->pluck('display_name')->join(', ');
            $user->syncRoles($validated['roles']);
            $newRoles = $user->roles()->pluck('display_name')->join(', ');

            if ($oldRoles !== $newRoles) {
                $roleChanges = [
                    'old' => $oldRoles,
                    'new' => $newRoles
                ];
            }
        }

        // 3. Manually Log activity (Single Consolidated Log)
        if (!empty($newAttributes) || $roleChanges) {
            $properties = [
                'attributes' => $newAttributes,
                'old' => $oldAttributes,
            ];

            if ($roleChanges) {
                $properties['attributes']['role_id'] = $roleChanges['new'];
                $properties['old']['role_id'] = $roleChanges['old'];
            }

            activity()
                ->performedOn($user)
                ->causedBy(auth()->user())
                ->event('updated')
                ->withProperties($properties)
                ->tap(function (\Spatie\Activitylog\Contracts\Activity $activity) use ($user) {
                    // Manually add snapshot since we aren't using the model's LogOptions due to saveQuietly
                    $activity->properties = $activity->properties->merge([
                        'snapshot' => [
                            'name' => $user->name,
                            'username' => $user->username,
                        ]
                    ]);
                })
                ->log('updated');
        }

        return redirect()->route('users.index')->with('success', '使用者更新成功');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        $user = User::findOrFail($id);

        if ($user->hasRole('super-admin')) {
             return back()->with('error', '無法刪除超級管理員帳號');
        }
        
        if ($user->id === auth()->id()) {
            return back()->with('error', '無法刪除自己');
        }

        $user->delete();

        return redirect()->route('users.index')->with('success', '使用者已刪除');
    }
}
