<?php

namespace Modules\Auth\Models;

use CodeIgniter\Model;

class UserSessionModel extends Model
{
    protected $table         = 'user_sessions';
    protected $primaryKey    = 'id';
    protected $returnType    = 'array';
    protected $useTimestamps = false;

    protected $allowedFields = [
        'user_id', 'session_token', 'ip_address', 'user_agent',
        'device_label', 'last_activity_at', 'revoked_at', 'created_at',
    ];

    public function startSession(int $userId, string $token, string $ip, ?string $userAgent, ?string $device = null): int
    {
        return (int) $this->insert([
            'user_id'          => $userId,
            'session_token'    => hash('sha256', $token),
            'ip_address'       => $ip,
            'user_agent'       => $userAgent,
            'device_label'     => $device,
            'last_activity_at' => date('Y-m-d H:i:s'),
            'created_at'       => date('Y-m-d H:i:s'),
        ], true);
    }

    public function touch(string $token): void
    {
        $this->where('session_token', hash('sha256', $token))
            ->set('last_activity_at', date('Y-m-d H:i:s'))
            ->update();
    }

    public function revoke(string $token): void
    {
        $this->where('session_token', hash('sha256', $token))
            ->set('revoked_at', date('Y-m-d H:i:s'))
            ->update();
    }

    public function isRevoked(string $token): bool
    {
        $row = $this->where('session_token', hash('sha256', $token))->first();

        return ! $row || $row['revoked_at'] !== null;
    }

    public function activeForUser(int $userId): array
    {
        return $this->where('user_id', $userId)
            ->where('revoked_at', null)
            ->orderBy('last_activity_at', 'DESC')
            ->findAll();
    }

    /**
     * Revoke every session for the user except the one currently in use
     * (used by "Force logout other devices").
     */
    public function revokeAllExcept(int $userId, string $keepToken): void
    {
        $this->where('user_id', $userId)
            ->where('session_token !=', hash('sha256', $keepToken))
            ->where('revoked_at', null)
            ->set('revoked_at', date('Y-m-d H:i:s'))
            ->update();
    }

    public function revokeAllForUser(int $userId): void
    {
        $this->where('user_id', $userId)
            ->where('revoked_at', null)
            ->set('revoked_at', date('Y-m-d H:i:s'))
            ->update();
    }
}
