using System.Data;
using Dapper;
using PlotLine.Models;

namespace PlotLine.Data;

public interface IOnboardingRepository
{
    Task<UserOnboardingState?> GetAsync(int userId);
    Task<UserOnboardingState> GetOrCreateAsync(int userId);
    Task<UserOnboardingState> SetCurrentStepAsync(int userId, string currentStep);
    Task<UserOnboardingState> SaveWritingJourneyAsync(int userId, string writingJourney);
    Task<UserOnboardingState> SaveWritingSoftwareAsync(int userId, string writingSoftware);
    Task<UserOnboardingState> SaveProjectAsync(int userId, int projectId);
    Task<UserOnboardingState> SaveBookAsync(int userId, int bookId);
    Task<UserOnboardingState> MarkCompletedAsync(int userId);
    Task<bool> ShouldShowWordCompanionHeaderAsync(int userId);
}

public sealed class OnboardingRepository(ISqlConnectionFactory connectionFactory) : IOnboardingRepository
{
    public async Task<UserOnboardingState?> GetAsync(int userId)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleOrDefaultAsync<UserOnboardingState>(
            "dbo.UserOnboarding_Get",
            new { UserID = userId },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> GetOrCreateAsync(int userId)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_GetOrCreate",
            new { UserID = userId },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> SetCurrentStepAsync(int userId, string currentStep)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_SetCurrentStep",
            new { UserID = userId, CurrentStep = currentStep },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> SaveWritingJourneyAsync(int userId, string writingJourney)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_SaveWritingJourney",
            new { UserID = userId, WritingJourney = writingJourney },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> SaveWritingSoftwareAsync(int userId, string writingSoftware)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_SaveWritingSoftware",
            new { UserID = userId, WritingSoftware = writingSoftware },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> SaveProjectAsync(int userId, int projectId)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_SaveProject",
            new { UserID = userId, ProjectID = projectId },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> SaveBookAsync(int userId, int bookId)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_SaveBook",
            new { UserID = userId, BookID = bookId },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<UserOnboardingState> MarkCompletedAsync(int userId)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<UserOnboardingState>(
            "dbo.UserOnboarding_MarkCompleted",
            new { UserID = userId },
            commandType: CommandType.StoredProcedure);
    }

    public async Task<bool> ShouldShowWordCompanionHeaderAsync(int userId)
    {
        using var connection = connectionFactory.CreateConnection();
        return await connection.QuerySingleAsync<bool>(
            "dbo.UserOnboarding_ShouldShowWordCompanionHeader",
            new { UserID = userId },
            commandType: CommandType.StoredProcedure);
    }
}
