using System.Text.RegularExpressions; using AVSCartonShipmentVerifier.Configuration; using AVSCartonShipmentVerifier.Data; using Microsoft.Extensions.Options; using MySqlConnector; namespace AVSCartonShipmentVerifier.Repositories; public sealed class CartonVerificationRepository( IVerificationDbConnectionFactory connectionFactory, IOptions options) : ICartonVerificationRepository { private static readonly Regex SqlIdentifierRegex = new("^[A-Za-z_][A-Za-z0-9_]*$", RegexOptions.Compiled); private readonly IVerificationDbConnectionFactory _connectionFactory = connectionFactory; private readonly CartonVerificationOptions _options = options.Value; public async Task UniqueNumberExistsAsync(string uniqueNumber, CancellationToken cancellationToken = default) { await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(cancellationToken); await using var command = connection.CreateCommand(); command.CommandText = $""" SELECT 1 FROM {QuoteIdentifier(_options.TableName)} WHERE {QuoteIdentifier(_options.QrColumnName)} = @uniqueNumber LIMIT 1; """; command.Parameters.AddWithValue("@uniqueNumber", uniqueNumber); var result = await command.ExecuteScalarAsync(cancellationToken); return result is not null; } public async Task MarkShipmentVerifiedAsync(string uniqueNumber, CancellationToken cancellationToken = default) { await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(cancellationToken); await using var command = connection.CreateCommand(); command.CommandText = $""" UPDATE {QuoteIdentifier(_options.TableName)} SET {QuoteIdentifier(_options.MovedToWarehouseColumnName)} = 1 WHERE {QuoteIdentifier(_options.QrColumnName)} = @uniqueNumber; """; command.Parameters.AddWithValue("@uniqueNumber", uniqueNumber); var affectedRows = await command.ExecuteNonQueryAsync(cancellationToken); return affectedRows > 0; } private static string QuoteIdentifier(string identifier) { if (!SqlIdentifierRegex.IsMatch(identifier)) { throw new InvalidOperationException($"Invalid SQL identifier configured: '{identifier}'."); } return $"`{identifier}`"; } }