using Dapper;
using FastBlog.Core.Abstractions.Repositories.Users;
using FastBlog.Core.Db;
using FastBlog.Core.Models.Users;

namespace FastBlog.Core.Repositories;

public sealed class SessionRepository(SqliteConnectionFactory connectionFactory) : ISessionRepository
{
    public async Task<Session?> Get(string token)
    {
        using var connection = connectionFactory.Create();
        const string sql =
            """
            SELECT s.*, u.UserName 
            FROM Sessions s
            JOIN Users u ON s.UserId = u.Id
            WHERE s.Token = @Token AND s.Active = true AND u.Deleted = false
            """;
        return await connection.QueryFirstOrDefaultAsync<Session>(sql, new { Token = token });
    }
    
    public async Task<Session?> Set(Session session)
    {
        using var connection = connectionFactory.Create();
        const string sql =
            """
            INSERT INTO Sessions (Token, UserId, CreatedAt, LastUsed, Active)
            VALUES (@Token, @UserId, @CreatedAt, @LastUsed, @Active)
            ON CONFLICT(Token) DO UPDATE SET LastUsed = @LastUsed
            RETURNING *
            """;
        return await connection.QueryFirstOrDefaultAsync<Session>(sql, session);
    }

    public async Task<Session?> Touch(string token)
    {
        using var connection = connectionFactory.Create();
        const string sql =
            """
            UPDATE Sessions
            SET LastUsed = @LastUsed
            WHERE Token = @Token
            RETURNING *
            """;
        return await connection.QueryFirstOrDefaultAsync<Session>(sql,
            new { Token = token, LastUsed = DateTime.UtcNow });
    }

    public async Task<bool> Deactivate(string token)
    {
        using var connection = connectionFactory.Create();
        const string sql = "UPDATE Sessions SET Active = false WHERE Token = @Token";
        var result = await connection.ExecuteAsync(sql, new { Token = token });
        return result > 0;
    }

    public async Task<bool> RemoveAll(int userId)
    {
        using var connection = connectionFactory.Create();
        const string sql = "DELETE FROM Sessions WHERE UserId = @UserId";
        var result = await connection.ExecuteAsync(sql, new { UserId = userId });
        return result > 0;
    }
}