<?php
namespace WorkbloomERP\Module\v0\Usuario\Repos;

use DateTimeImmutable;
use WorkbloomERP\Services\DBService;
use WorkbloomERP\Module\v0\Usuario\Models\UsuarioSessionModel;

class UsuarioSessionRepo {
    protected string $usuarioSessionTable = 'usuario_session';

    public function __construct(
        private DBService $db
    ) {}

    public function insert(UsuarioSessionModel $usuarioSessionModel): ?UsuarioSessionModel {
        $query = 
        "INSERT INTO {$this->usuarioSessionTable} (
            uuid,
            usuario_id,
            user_agent,
            ip_address,
            token_hash,
            created_at
        ) VALUES (
            :uuid,
            :usuario_id,
            :user_agent,
            :ip_address,
            :token_hash,
            :created_at
        )";

        $usuarioSessionModel->setCreatedAt(new DateTimeImmutable());

        $this->db->execute(
            sql: $query,
            params: [
                ':uuid' => $usuarioSessionModel->getUuid(),
                ':usuario_id' => $usuarioSessionModel->getUsuarioId(),
                ':user_agent' => $usuarioSessionModel->getUserAgent(),
                ':ip_address' => $usuarioSessionModel->getIpAddress(),
                ':token_hash' => $usuarioSessionModel->getTokenHash(),
                ':created_at' => $usuarioSessionModel->getCreatedAt()->format('Y-m-d H:i:s')
            ]
        );

        $usuarioSessionModel->setId($this->db->lastInsertId());
        return $usuarioSessionModel;
    }

    public function update(UsuarioSessionModel $usuarioSessionModel): bool {
        $query = 
        "UPDATE {$this->usuarioSessionTable} SET
            usuario_id = :usuario_id,
            user_agent = :user_agent,
            ip_address = :ip_address,
            token_hash = :token_hash,
            revoked_at = :revoked_at
        WHERE id = :id OR uuid = :uuid";

        return $this->db->execute(
            sql: $query,
            params: [
                ':id' => $usuarioSessionModel->getId(),
                ':uuid' => $usuarioSessionModel->getUuid(),
                ':usuario_id' => $usuarioSessionModel->getUsuarioId(),
                ':user_agent' => $usuarioSessionModel->getUserAgent(),
                ':ip_address' => $usuarioSessionModel->getIpAddress(),
                ':token_hash' => $usuarioSessionModel->getTokenHash(),
                ':revoked_at' => $usuarioSessionModel->getRevokedAt() ? $usuarioSessionModel->getRevokedAt()->format('Y-m-d H:i:s') : null
            ]
        );
    }

    public function findByIdentifier(string $identifier, mixed $value): ?UsuarioSessionModel {
        $query =
        "SELECT
            id,
            uuid,
            usuario_id,
            user_agent,
            ip_address,
            token_hash,
            created_at,
            revoked_at
        FROM {$this->usuarioSessionTable}
        WHERE $identifier = :value
        LIMIT 1";

        $result = $this->db->fetchOne(
            sql: $query,
            params: [':value' => $value]
        );

        return $result ? $this->mapToModel($result) : null;
    }

    private function mapToModel(array $data) {
        return new UsuarioSessionModel(
            id: $data['id'],
            uuid: $data['uuid'],
            usuario_id: $data['usuario_id'],
            user_agent: $data['user_agent'],
            ip_address: $data['ip_address'],
            token_hash: $data['token_hash'],
            created_at: $data['created_at'] ? new DateTimeImmutable($data['created_at']) : null,
            revoked_at: $data['revoked_at'] ? new DateTimeImmutable($data['revoked_at']) : null,
        );
    }
}