<?php

namespace App\Http\Controllers\Tenant;

use App\Http\Controllers\Controller;
use App\Models\AuditLog;
use App\Models\Branch;
use App\Models\Counter;
use App\Models\Department;
use App\Models\Employee;
use App\Models\LoginHistory;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use App\Models\UserPermissionOverride;
use App\Models\UserType;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $tenantId = auth()->user()->tenant_id;
        $query = User::where('tenant_id', $tenantId)->with(['roles', 'defaultBranch', 'department', 'employee']);

        // Search
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%")
                    ->orWhere('mobile', 'like', "%{$search}%")
                    ->orWhere('username', 'like', "%{$search}%")
                    ->orWhereHas('employee', function ($eq) use ($search) {
                        $eq->where('employee_code', 'like', "%{$search}%");
                    });
            });
        }

        // Filters
        if ($request->filled('role_id')) {
            $query->whereHas('roles', function ($q) use ($request) {
                $q->where('roles.id', $request->role_id);
            });
        }

        if ($request->filled('branch_id')) {
            $query->where('default_branch_id', $request->branch_id);
        }

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        $users = $query->paginate(15);

        $roles = Role::where(function ($q) use ($tenantId) {
            $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
        })->get();

        $branches = Branch::where('tenant_id', $tenantId)->get();

        return view('tenant.users.index', compact('users', 'roles', 'branches'));
    }

    public function create()
    {
        $tenantId = auth()->user()->tenant_id;
        $employees = Employee::where('tenant_id', $tenantId)->whereDoesntHave('user')->get();
        $roles = Role::where(function ($q) use ($tenantId) {
            $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
        })->get();
        $branches = Branch::where('tenant_id', $tenantId)->get();
        $departments = Department::where('tenant_id', $tenantId)->get();
        $counters = Counter::where('tenant_id', $tenantId)->get();

        return view('tenant.users.create', compact('employees', 'roles', 'branches', 'departments', 'counters'));
    }

    public function store(Request $request)
    {
        $tenantId = auth()->user()->tenant_id;

        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', Rule::unique('users', 'email')],
            'username' => ['required', 'string', 'max:100', Rule::unique('users', 'username')],
            'password' => ['required', 'confirmed', Password::min(8)->mixedCase()->numbers()],
            'default_branch_id' => ['required', Rule::exists('branches', 'id')->where('tenant_id', $tenantId)],
            'role_id' => ['required', Rule::exists('roles', 'id')->where(fn ($query) => $query->where(fn ($role) => $role->whereNull('tenant_id')->orWhere('tenant_id', $tenantId)))],
            'employee_id' => ['nullable', Rule::exists('employees', 'id')->where('tenant_id', $tenantId), Rule::unique('users', 'employee_id')],
            'department_id' => ['nullable', Rule::exists('departments', 'id')->where('tenant_id', $tenantId)],
            'counter_id' => ['nullable', Rule::exists('counters', 'id')->where('tenant_id', $tenantId)],
            'allowed_branches' => ['nullable', 'array'],
            'allowed_branches.*' => [Rule::exists('branches', 'id')->where('tenant_id', $tenantId)],
            'data_scope_override' => ['nullable', Rule::in(['own', 'branch', 'multi_branch', 'tenant'])],
        ]);

        $tenantType = UserType::where('slug', 'tenant_user')->first();

        $user = User::create([
            'tenant_id' => $tenantId,
            'employee_id' => $request->employee_id,
            'user_type_id' => $tenantType->id,
            'name' => $request->name,
            'email' => $request->email,
            'mobile' => $request->mobile,
            'username' => $request->username,
            'password' => Hash::make($request->password),
            'default_branch_id' => $request->default_branch_id,
            'department_id' => $request->department_id,
            'counter_id' => $request->counter_id,
            'data_scope_override' => $request->data_scope_override,
            'language' => 'en',
            'timezone' => 'Asia/Dubai',
            'status' => 'active',
            'must_change_password' => $request->boolean('must_change_password'),
            'mfa_enabled' => $request->boolean('mfa_enabled'),
            'allow_web_login' => $request->boolean('allow_web_login', true),
            'allow_mobile_login' => $request->boolean('allow_mobile_login', true),
            'created_by' => auth()->id(),
        ]);

        $user->roles()->sync([$request->role_id]);

        if ($request->has('allowed_branches')) {
            $user->allowedBranches()->sync($request->allowed_branches);
        } else {
            $user->allowedBranches()->sync([$request->default_branch_id]);
        }

        AuditLog::record('users', 'user.created', $user);

        return redirect()->route('app.users.index')->with('status', 'User account created successfully.');
    }

    public function edit($id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->findOrFail($id);
        $roles = Role::where(function ($q) use ($tenantId) {
            $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
        })->get();
        $branches = Branch::where('tenant_id', $tenantId)->get();

        return view('tenant.users.edit', compact('user', 'roles', 'branches'));
    }

    public function update(Request $request, $id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->findOrFail($id);

        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', Rule::unique('users', 'email')->ignore($user->id)],
            'username' => ['required', 'string', 'max:100', Rule::unique('users', 'username')->ignore($user->id)],
            'default_branch_id' => ['required', Rule::exists('branches', 'id')->where('tenant_id', $tenantId)],
            'role_id' => ['required', Rule::exists('roles', 'id')->where(fn ($query) => $query->where(fn ($role) => $role->whereNull('tenant_id')->orWhere('tenant_id', $tenantId)))],
            'status' => ['required', Rule::in(['active', 'suspended', 'inactive', 'locked'])],
            'allowed_branches' => ['nullable', 'array'],
            'allowed_branches.*' => [Rule::exists('branches', 'id')->where('tenant_id', $tenantId)],
            'data_scope_override' => ['nullable', Rule::in(['own', 'branch', 'multi_branch', 'tenant'])],
        ]);

        $user->update([
            'name' => $request->name,
            'email' => $request->email,
            'mobile' => $request->mobile,
            'username' => $request->username,
            'default_branch_id' => $request->default_branch_id,
            'data_scope_override' => $request->data_scope_override,
            'status' => $request->status,
            'allow_web_login' => $request->boolean('allow_web_login'),
            'allow_mobile_login' => $request->boolean('allow_mobile_login'),
        ]);

        $user->roles()->sync([$request->role_id]);

        if ($request->has('allowed_branches')) {
            $user->allowedBranches()->sync($request->allowed_branches);
        }

        AuditLog::record('users', 'user.updated', $user);

        return redirect()->route('app.users.index')->with('status', 'User account updated successfully.');
    }

    public function overrides($id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->with('permissionOverrides')->findOrFail($id);
        $permissions = Permission::all()->groupBy('module');

        $overrides = $user->permissionOverrides->keyBy('permission_id');

        return view('tenant.users.overrides', compact('user', 'permissions', 'overrides'));
    }

    public function updateOverrides(Request $request, $id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->findOrFail($id);

        // $request->overrides is array of permission_id => 'allow' | 'deny' | 'inherit'
        $overrideData = $request->input('overrides', []);

        // Delete existing overrides for clean state
        UserPermissionOverride::where('user_id', $user->id)->delete();

        foreach ($overrideData as $permissionId => $setting) {
            if ($setting === 'allow') {
                UserPermissionOverride::create([
                    'user_id' => $user->id,
                    'permission_id' => $permissionId,
                    'is_allowed' => true,
                ]);
            } elseif ($setting === 'deny') {
                UserPermissionOverride::create([
                    'user_id' => $user->id,
                    'permission_id' => $permissionId,
                    'is_allowed' => false,
                ]);
            }
            // 'inherit' means no row in user_permission_overrides table
        }

        AuditLog::record('users', 'user.permission_overrides_updated', $user);

        return redirect()->route('app.users.index')->with('status', 'User permission overrides saved successfully.');
    }

    public function resetPassword(Request $request, $id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->findOrFail($id);

        $request->validate(['password' => ['required', Password::min(8)->mixedCase()->numbers()]]);

        $user->update([
            'password' => Hash::make($request->password),
            'must_change_password' => true,
        ]);

        AuditLog::record('users', 'user.password_reset', $user);

        return back()->with('status', 'Password reset successfully. User will be prompted to change password on next login.');
    }

    public function toggleStatus($id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->findOrFail($id);

        $newStatus = ($user->status === 'active') ? 'suspended' : 'active';
        $user->update(['status' => $newStatus]);

        AuditLog::record('users', 'user.status_changed', $user, ['new_status' => $newStatus]);

        return back()->with('status', "User account has been {$newStatus}.");
    }

    public function loginHistory($id)
    {
        $tenantId = auth()->user()->tenant_id;
        $user = User::where('tenant_id', $tenantId)->findOrFail($id);
        $history = LoginHistory::where('user_id', $user->id)->latest()->paginate(20);

        return view('tenant.users.login_history', compact('user', 'history'));
    }
}
