<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Role;
use App\Models\Permission;
use App\Models\UserActivity;
use Illuminate\Support\Facades\DB;

class RoleManagementController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware(function ($request, $next) {
            if (!auth()->user()->hasPermission('manage_roles')) {
                abort(403, 'Unauthorized access to role management');
            }
            return $next($request);
        });
    }

    /**
     * Display roles listing
     */
    public function index()
    {
        $roles = Role::withCount('users')->latest()->get();
        return view('admin.roles.index', compact('roles'));
    }

    /**
     * Show create role form
     */
    public function create()
    {
        $permissions = Permission::orderBy('group')->orderBy('display_name')->get()->groupBy('group');
        return view('admin.roles.create', compact('permissions'));
    }

    /**
     * Store a new role
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255|unique:roles,name|regex:/^[a-z_]+$/',
            'display_name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'permissions' => 'array',
            'permissions.*' => 'exists:permissions,id'
        ], [
            'name.regex' => 'Role name must be lowercase with underscores only (e.g., admin_user)'
        ]);

        DB::beginTransaction();
        try {
            // Create the role
            $role = Role::create([
                'name' => $validated['name'],
                'display_name' => $validated['display_name'],
                'description' => $validated['description'] ?? null,
                'is_active' => true
            ]);

            // Attach permissions
            if (!empty($validated['permissions'])) {
                $role->permissions()->attach($validated['permissions']);
            }

            // Log activity
            UserActivity::create([
                'user_id' => auth()->id(),
                'action' => 'created_role',
                'description' => "Created role: {$role->display_name}",
                'properties' => [
                    'role_id' => $role->id,
                    'permissions_count' => count($validated['permissions'] ?? [])
                ],
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent()
            ]);

            DB::commit();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Role created successfully!',
                    'role' => $role
                ]);
            }

            return redirect()->route('admin.roles')->with('success', 'Role created successfully!');
        } catch (\Exception $e) {
            DB::rollback();
            
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to create role: ' . $e->getMessage()
                ], 500);
            }

            return back()->withErrors(['error' => 'Failed to create role'])->withInput();
        }
    }

    /**
     * Show edit role form
     */
    public function edit(Role $role)
    {
        // Prevent editing super admin role
        if ($role->name === 'super_admin') {
            return redirect()->route('admin.roles')->with('error', 'Super Admin role cannot be edited');
        }

        $permissions = Permission::orderBy('group')->orderBy('display_name')->get()->groupBy('group');
        $rolePermissions = $role->permissions->pluck('id')->toArray();
        
        return view('admin.roles.edit', compact('role', 'permissions', 'rolePermissions'));
    }

    /**
     * Update a role
     */
    public function update(Request $request, Role $role)
    {
        // Prevent editing super admin role
        if ($role->name === 'super_admin') {
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Super Admin role cannot be edited'
                ], 403);
            }
            return redirect()->route('admin.roles')->with('error', 'Super Admin role cannot be edited');
        }

        $validated = $request->validate([
            'display_name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'permissions' => 'array',
            'permissions.*' => 'exists:permissions,id',
            'is_active' => 'boolean'
        ]);

        DB::beginTransaction();
        try {
            // Update role details
            $role->update([
                'display_name' => $validated['display_name'],
                'description' => $validated['description'] ?? null,
                'is_active' => $request->has('is_active')
            ]);

            // Sync permissions
            $role->permissions()->sync($validated['permissions'] ?? []);

            // Log activity
            UserActivity::create([
                'user_id' => auth()->id(),
                'action' => 'updated_role',
                'description' => "Updated role: {$role->display_name}",
                'properties' => [
                    'role_id' => $role->id,
                    'permissions_count' => count($validated['permissions'] ?? [])
                ],
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent()
            ]);

            DB::commit();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Role updated successfully!'
                ]);
            }

            return redirect()->route('admin.roles')->with('success', 'Role updated successfully!');
        } catch (\Exception $e) {
            DB::rollback();
            
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to update role: ' . $e->getMessage()
                ], 500);
            }

            return back()->withErrors(['error' => 'Failed to update role'])->withInput();
        }
    }

    /**
     * Delete a role
     */
    public function destroy(Request $request, Role $role)
    {
        // Prevent deletion of system roles
        if (in_array($role->name, ['super_admin', 'admin', 'hr_manager', 'viewer'])) {
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'System roles cannot be deleted'
                ], 403);
            }
            return redirect()->route('admin.roles')->with('error', 'System roles cannot be deleted');
        }

        // Check if role has users
        if ($role->users()->exists()) {
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Cannot delete role with assigned users'
                ], 400);
            }
            return redirect()->route('admin.roles')->with('error', 'Cannot delete role with assigned users');
        }

        DB::beginTransaction();
        try {
            // Log activity
            UserActivity::create([
                'user_id' => auth()->id(),
                'action' => 'deleted_role',
                'description' => "Deleted role: {$role->display_name}",
                'properties' => [
                    'role_name' => $role->name,
                    'role_display_name' => $role->display_name
                ],
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent()
            ]);

            // Delete role (will cascade delete role_permissions)
            $role->delete();

            DB::commit();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Role deleted successfully!'
                ]);
            }

            return redirect()->route('admin.roles')->with('success', 'Role deleted successfully!');
        } catch (\Exception $e) {
            DB::rollback();
            
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to delete role: ' . $e->getMessage()
                ], 500);
            }

            return redirect()->route('admin.roles')->with('error', 'Failed to delete role');
        }
    }

    /**
     * View permissions management
     */
    public function permissions()
    {
        $permissions = Permission::orderBy('group')->orderBy('display_name')->get()->groupBy('group');
        return view('admin.roles.permissions', compact('permissions'));
    }

    /**
     * Show role details (API endpoint)
     */
    public function show(Request $request, Role $role)
    {
        try {
            \Log::info('Role show method called', ['role_id' => $role->id, 'expects_json' => $request->expectsJson()]);

            if ($request->expectsJson()) {
                $roleData = $role->load(['permissions', 'users'])
                                ->loadCount(['permissions', 'users']);

                return response()->json([
                    'success' => true,
                    'role' => $roleData
                ]);
            }

            return redirect()->route('admin.roles.edit', $role);
        } catch (\Exception $e) {
            \Log::error('Error in role show method', ['error' => $e->getMessage()]);

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Error loading role: ' . $e->getMessage()
                ], 500);
            }

            return redirect()->route('admin.roles')->with('error', 'Role not found');
        }
    }

    /**
     * Duplicate a role
     */
    public function duplicate(Request $request, Role $role)
    {
        DB::beginTransaction();
        try {
            // Create new role with copied data
            $newRole = Role::create([
                'name' => $role->name . '_copy_' . time(),
                'display_name' => $role->display_name . ' (Copy)',
                'description' => $role->description,
                'is_active' => false // New roles start inactive
            ]);

            // Copy permissions
            $permissionIds = $role->permissions->pluck('id')->toArray();
            if (!empty($permissionIds)) {
                $newRole->permissions()->attach($permissionIds);
            }

            // Log activity
            UserActivity::create([
                'user_id' => auth()->id(),
                'action' => 'duplicated_role',
                'description' => "Duplicated role: {$role->display_name} -> {$newRole->display_name}",
                'properties' => [
                    'original_role_id' => $role->id,
                    'new_role_id' => $newRole->id,
                    'permissions_count' => count($permissionIds)
                ],
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent()
            ]);

            DB::commit();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Role duplicated successfully!',
                    'new_role_id' => $newRole->id
                ]);
            }

            return redirect()->route('admin.roles.edit', $newRole)
                           ->with('success', 'Role duplicated successfully!');

        } catch (\Exception $e) {
            DB::rollback();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to duplicate role: ' . $e->getMessage()
                ], 500);
            }

            return back()->withErrors(['error' => 'Failed to duplicate role']);
        }
    }

    /**
     * Toggle role status (activate/deactivate)
     */
    public function toggleStatus(Request $request, Role $role)
    {
        // Prevent status change for super admin role
        if ($role->name === 'super_admin') {
            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Super Admin role status cannot be changed'
                ], 403);
            }
            return redirect()->route('admin.roles')->with('error', 'Super Admin role status cannot be changed');
        }

        DB::beginTransaction();
        try {
            $newStatus = !$role->is_active;
            $role->update(['is_active' => $newStatus]);

            // Log activity
            UserActivity::create([
                'user_id' => auth()->id(),
                'action' => $newStatus ? 'activated_role' : 'deactivated_role',
                'description' => ($newStatus ? 'Activated' : 'Deactivated') . " role: {$role->display_name}",
                'properties' => [
                    'role_id' => $role->id,
                    'new_status' => $newStatus
                ],
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent()
            ]);

            DB::commit();

            $message = $newStatus ? 'Role activated successfully!' : 'Role deactivated successfully!';

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => $message
                ]);
            }

            return redirect()->route('admin.roles')->with('success', $message);

        } catch (\Exception $e) {
            DB::rollback();

            if ($request->expectsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to toggle role status: ' . $e->getMessage()
                ], 500);
            }

            return back()->withErrors(['error' => 'Failed to toggle role status']);
        }
    }
}