<?php
declare(strict_types=1);

namespace App\Modules\Users\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\Pagination;
use App\Modules\Users\Models\Employee;
use App\Modules\Roles\Models\Role;

class UserController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();
        $perPage = (int) config('app.per_page', 25);
        $page = max(1, (int) $request->get('page', 1));
        $search = trim((string) $request->get('q', ''));
        $statusFilter = $request->get('status', '');

        $where = "e.is_archived = 0";
        $params = [];

        if ($search !== '') {
            $where .= " AND (e.full_name_ar LIKE ? OR e.username LIKE ? OR e.email LIKE ?)";
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
        }

        if ($statusFilter === 'active') {
            $where .= " AND e.is_active = 1";
        } elseif ($statusFilter === 'inactive') {
            $where .= " AND e.is_active = 0";
        }

        $countRow = $db->selectOne("SELECT COUNT(*) as cnt FROM employees e WHERE {$where}", $params);
        $total = (int) ($countRow['cnt'] ?? 0);
        $pagination = Pagination::paginate($total, $perPage, $page);
        $offset = ($page - 1) * $perPage;

        $employees = $db->select("
            SELECT e.*, b.name_ar as branch_name
            FROM employees e
            LEFT JOIN branches b ON b.id = e.branch_id
            WHERE {$where}
            ORDER BY e.created_at DESC
            LIMIT {$perPage} OFFSET {$offset}
        ", $params);

        return $this->view('Users.Views.index', [
            'employees'  => $employees,
            'pagination' => $pagination,
            'search'     => $search,
            'status'     => $statusFilter,
        ]);
    }

    public function create(Request $request): Response
    {
        $roles = Role::allActive();
        $branches = App::getInstance()->db()->select("SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar");
        return $this->view('Users.Views.create', [
            'roles'    => $roles,
            'branches' => $branches,
        ]);
    }

    public function store(Request $request): Response
    {
        $data = $this->validate($request->all(), [
            'username'     => 'required|string|min:3|max:50',
            'password'     => 'required|string|min:8',
            'full_name_ar' => 'required|string|min:3|max:200',
            'full_name_en' => 'nullable|string|max:200',
            'email'        => 'nullable|email',
            'phone'        => 'nullable|string|max:20',
            'branch_id'    => 'nullable|integer',
        ]);

        $existing = App::getInstance()->db()->selectOne("SELECT id FROM employees WHERE username = ?", [$data['username']]);
        if ($existing) {
            return $this->redirect('/users/create')
                ->withError('اسم المستخدم مستخدم بالفعل')
                ->withInput($request->all());
        }

        $cost = (int) config('auth.password_bcrypt_cost', 12);
        $hash = password_hash($data['password'], PASSWORD_BCRYPT, ['cost' => $cost]);

        $employee = Employee::create([
            'username'              => $data['username'],
            'password_hash'         => $hash,
            'full_name_ar'          => $data['full_name_ar'],
            'full_name_en'          => $data['full_name_en'] ?? null,
            'email'                 => $data['email'] ?? null,
            'phone'                 => $data['phone'] ?? null,
            'branch_id'             => $data['branch_id'] ? (int) $data['branch_id'] : null,
            'is_active'             => 1,
            'force_password_change' => 1,
        ]);

        $db = App::getInstance()->db();
        $currentEmp = App::getInstance()->currentEmployee();
        $performedBy = $currentEmp ? (int) $currentEmp->id : 0;

        $roleIds = $request->post('roles', []);
        $roleExpires = $request->post('role_expires', []);
        if (is_array($roleIds)) {
            foreach ($roleIds as $roleId) {
                $expiresAt = $roleExpires[$roleId] ?? null;
                $db->insert('employee_roles', [
                    'employee_id' => (int) $employee->id,
                    'role_id'     => (int) $roleId,
                    'assigned_at' => date('Y-m-d H:i:s'),
                    'assigned_by' => $performedBy,
                    'expires_at'  => ($expiresAt && $expiresAt !== '') ? $expiresAt : null,
                    'is_active'   => 1,
                ]);
            }
        }

        $branchIds = $request->post('branch_ids', []);
        if (is_array($branchIds) && !empty($branchIds)) {
            $isFirst = true;
            foreach ($branchIds as $bid) {
                $db->insert('employee_branches', [
                    'employee_id' => (int) $employee->id,
                    'branch_id'   => (int) $bid,
                    'is_primary'  => $isFirst ? 1 : 0,
                    'assigned_at' => date('Y-m-d H:i:s'),
                    'assigned_by' => $performedBy,
                ]);
                $isFirst = false;
            }
        } elseif ($data['branch_id']) {
            $db->insert('employee_branches', [
                'employee_id' => (int) $employee->id,
                'branch_id'   => (int) $data['branch_id'],
                'is_primary'  => 1,
                'assigned_at' => date('Y-m-d H:i:s'),
                'assigned_by' => $performedBy,
            ]);
        }

        $db->insert('password_history', [
            'employee_id'   => (int) $employee->id,
            'password_hash' => $hash,
            'created_at'    => date('Y-m-d H:i:s'),
        ]);

        return $this->redirect('/users')->withSuccess('تم إنشاء الموظف بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $employee = Employee::find((int) $id);
        if (!$employee) {
            return $this->redirect('/users')->withError('الموظف غير موجود');
        }

        $roles = $employee->getRolesWithNames();
        $sessions = \App\Modules\Auth\Models\ActiveSession::getActiveForEmployee((int) $employee->id);

        return $this->view('Users.Views.show', [
            'employee' => $employee,
            'roles'    => $roles,
            'sessions' => $sessions,
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $employee = Employee::find((int) $id);
        if (!$employee) {
            return $this->redirect('/users')->withError('الموظف غير موجود');
        }

        $allRoles = Role::allActive();
        $employeeRoles = $employee->getRolesWithNames();
        $currentRoleIds = array_column($employeeRoles, 'id');
        $roleExpirations = [];
        foreach ($employeeRoles as $er) {
            $roleExpirations[(int) $er['id']] = $er['expires_at'] ?? '';
        }
        $branches = App::getInstance()->db()->select("SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar");

        return $this->view('Users.Views.edit', [
            'employee'        => $employee,
            'allRoles'        => $allRoles,
            'currentRoleIds'  => $currentRoleIds,
            'roleExpirations' => $roleExpirations,
            'branches'        => $branches,
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $employee = Employee::find((int) $id);
        if (!$employee) {
            return $this->redirect('/users')->withError('الموظف غير موجود');
        }

        $data = $this->validate($request->all(), [
            'full_name_ar' => 'required|string|min:3|max:200',
            'full_name_en' => 'nullable|string|max:200',
            'email'        => 'nullable|email',
            'phone'        => 'nullable|string|max:20',
            'branch_id'    => 'nullable|integer',
            'is_active'    => 'nullable|in:0,1',
        ]);

        $updateData = [
            'full_name_ar' => $data['full_name_ar'],
            'full_name_en' => $data['full_name_en'] ?? null,
            'email'        => $data['email'] ?? null,
            'phone'        => $data['phone'] ?? null,
            'branch_id'    => isset($data['branch_id']) && $data['branch_id'] !== '' ? (int) $data['branch_id'] : null,
            'is_active'    => isset($data['is_active']) ? (int) $data['is_active'] : (int) $employee->is_active,
        ];

        $newPassword = $request->post('new_password', '');
        if ($newPassword !== '') {
            if (mb_strlen($newPassword) < 8) {
                return $this->redirect("/users/{$id}/edit")->withError('كلمة المرور يجب أن تكون 8 أحرف على الأقل');
            }
            $cost = (int) config('auth.password_bcrypt_cost', 12);
            $updateData['password_hash'] = password_hash($newPassword, PASSWORD_BCRYPT, ['cost' => $cost]);
            $updateData['force_password_change'] = 1;
        }

        $employee->update($updateData);

        $db = App::getInstance()->db();
        $db->delete('employee_roles', '`employee_id` = ?', [$employee->id]);
        $roleIds = $request->post('roles', []);
        $roleExpires = $request->post('role_expires', []);
        if (is_array($roleIds)) {
            $currentEmp = App::getInstance()->currentEmployee();
            foreach ($roleIds as $roleId) {
                $expiresAt = $roleExpires[$roleId] ?? null;
                $db->insert('employee_roles', [
                    'employee_id' => (int) $employee->id,
                    'role_id'     => (int) $roleId,
                    'assigned_at' => date('Y-m-d H:i:s'),
                    'assigned_by' => $currentEmp ? (int) $currentEmp->id : null,
                    'expires_at'  => ($expiresAt && $expiresAt !== '') ? $expiresAt : null,
                    'is_active'   => 1,
                ]);
            }
        }

        return $this->redirect('/users')->withSuccess('تم تحديث بيانات الموظف بنجاح');
    }

    public function activity(Request $request, string $id): Response
    {
        $employee = Employee::find((int) $id);
        if (!$employee) {
            return $this->redirect('/users')->withError('الموظف غير موجود');
        }

        $db = App::getInstance()->db();
        $attempts = $db->select(
            "SELECT * FROM login_attempts WHERE username = ? ORDER BY attempted_at DESC LIMIT 50",
            [$employee->username]
        );

        return $this->view('Users.Views.activity', [
            'employee' => $employee,
            'attempts' => $attempts,
        ]);
    }
}