<?php

namespace Modules\Auth\Models;

use CodeIgniter\Model;
use Modules\Auth\Entities\UserEntity;

class UserModel extends Model
{
    protected $table            = 'users';
    protected $primaryKey       = 'id';
    protected $useAutoIncrement = true;
    protected $returnType       = UserEntity::class;
    protected $useSoftDeletes   = true;
    protected $protectFields    = true;

    protected $allowedFields = [
        'uuid', 'first_name', 'last_name', 'username', 'email', 'phone',
        'password_hash', 'password_changed_at', 'must_change_password',
        'avatar_path', 'role_id', 'branch_id', 'department_id', 'status',
        'email_verified_at', 'two_factor_enabled', 'two_factor_secret',
        'failed_login_count', 'locked_until', 'last_login_at', 'last_login_ip',
        'remember_token',
        'tpin_hash', 'tpin_set_at', 'tpin_required', 'tpin_failed_count', 'tpin_locked_until',
        'created_by', 'updated_by',
    ];

    protected $useTimestamps = true;
    protected $dateFormat    = 'datetime';
    protected $createdField  = 'created_at';
    protected $updatedField  = 'updated_at';
    protected $deletedField  = 'deleted_at';

    protected $validationRules = [
        'id'         => 'permit_empty|integer',
        'first_name' => 'required|min_length[2]|max_length[100]',
        'last_name'  => 'required|min_length[2]|max_length[100]',
        'username'   => 'required|alpha_numeric_punct|min_length[3]|max_length[100]|is_unique[users.username,id,{id}]',
        'email'      => 'required|valid_email|max_length[191]|is_unique[users.email,id,{id}]',
        'phone'      => 'permit_empty|max_length[30]',
        'status'     => 'permit_empty|in_list[active,inactive,locked]',
    ];

    protected $validationMessages = [
        'username' => [
            'is_unique' => 'That username is already taken.',
        ],
        'email' => [
            'is_unique' => 'That email address is already registered.',
        ],
    ];

    public function findByLogin(string $identifier): ?UserEntity
    {
        return $this->groupStart()
            ->where('username', $identifier)
            ->orWhere('email', $identifier)
            ->groupEnd()
            ->first();
    }

    public function touchLastLogin(int $userId, string $ip): void
    {
        $this->update($userId, [
            'last_login_at' => date('Y-m-d H:i:s'),
            'last_login_ip' => $ip,
        ]);
    }

    public function incrementFailedLogins(int $userId): int
    {
        $user = $this->find($userId);
        if (! $user) {
            return 0;
        }

        $count = $user->failed_login_count + 1;
        $this->update($userId, ['failed_login_count' => $count]);

        return $count;
    }

    public function resetFailedLogins(int $userId): void
    {
        $this->update($userId, ['failed_login_count' => 0, 'locked_until' => null]);
    }

    public function lockUntil(int $userId, string $datetime): void
    {
        $this->update($userId, ['locked_until' => $datetime, 'status' => 'locked']);
    }

    /**
     * Build the filtered/searched query used by the Users list screen.
     * Kept separate from pagination so the controller can also fetch
     * export data (CSV/print) using the exact same filters.
     */
    public function scopeForList(?string $search, ?string $status, ?int $roleId, ?int $branchId, ?int $departmentId, bool $withTrashed = false): self
    {
        if ($withTrashed) {
            $this->withDeleted();
        }

        if ($search) {
            $this->groupStart()
                ->like('first_name', $search)
                ->orLike('last_name', $search)
                ->orLike('username', $search)
                ->orLike('email', $search)
                ->groupEnd();
        }

        if ($status) {
            $this->where('status', $status);
        }
        if ($roleId) {
            $this->where('role_id', $roleId);
        }
        if ($branchId) {
            $this->where('branch_id', $branchId);
        }
        if ($departmentId) {
            $this->where('department_id', $departmentId);
        }

        return $this;
    }

    public function isUsernameOrEmailTaken(string $username, string $email, ?int $exceptId = null): bool
    {
        $builder = $this->builder();
        $builder->groupStart()
            ->where('username', $username)
            ->orWhere('email', $email)
            ->groupEnd();

        if ($exceptId) {
            $builder->where('id !=', $exceptId);
        }

        return $builder->countAllResults() > 0;
    }

    /**
     * Ensure {id} validation placeholders are available when updating.
     */
    public function update($id = null, $data = null): bool
    {
        if (is_array($data) && $id !== null && ! is_array($id)) {
            $data['id'] = $id;
        }

        return parent::update($id, $data);
    }

    public function restore(int $userId): void
    {
        $this->update($userId, ['deleted_at' => null]);
    }

    public function setStatus(int $userId, string $status): void
    {
        $this->update($userId, ['status' => $status]);
    }
}
