diff --git a/api/CourseRegistration.Application/Services/IMathService.cs b/api/CourseRegistration.Application/Services/IMathService.cs
new file mode 100644
index 0000000..5a0c780
--- /dev/null
+++ b/api/CourseRegistration.Application/Services/IMathService.cs
@@ -0,0 +1,16 @@
+namespace CourseRegistration.Application.Services;
+
+///
+/// Interface for mathematical utility operations.
+///
+public interface IMathService
+{
+ ///
+ /// Calculates the factorial of a non-negative integer.
+ ///
+ /// A non-negative integer whose factorial is to be computed.
+ /// The factorial of as a .
+ /// Thrown when is negative.
+ /// Thrown when the result exceeds .
+ long CalculateFactorial(int n);
+}
diff --git a/api/CourseRegistration.Application/Services/MathService.cs b/api/CourseRegistration.Application/Services/MathService.cs
new file mode 100644
index 0000000..89723eb
--- /dev/null
+++ b/api/CourseRegistration.Application/Services/MathService.cs
@@ -0,0 +1,34 @@
+namespace CourseRegistration.Application.Services;
+
+///
+/// Provides mathematical utility operations such as factorial calculation.
+///
+public class MathService : IMathService
+{
+ // 20! is the largest factorial that fits in a long (Int64)
+ private const int MaxFactorialInput = 20;
+
+ ///
+ /// Calculates the factorial of a non-negative integer iteratively.
+ ///
+ /// A non-negative integer (0 – 20) whose factorial is to be computed.
+ /// The factorial of .
+ /// Thrown when is negative.
+ /// Thrown when exceeds 20 and the result would overflow .
+ public long CalculateFactorial(int n)
+ {
+ if (n < 0)
+ throw new ArgumentOutOfRangeException(nameof(n), "Factorial is not defined for negative numbers.");
+
+ if (n > MaxFactorialInput)
+ throw new OverflowException($"Input {n} is too large; factorial exceeds the range of a 64-bit integer (max supported: {MaxFactorialInput}).");
+
+ long result = 1;
+ for (int i = 2; i <= n; i++)
+ {
+ result *= i;
+ }
+
+ return result;
+ }
+}
diff --git a/api/CourseRegistration.Tests/Services/MathServiceTests.cs b/api/CourseRegistration.Tests/Services/MathServiceTests.cs
new file mode 100644
index 0000000..474e5ce
--- /dev/null
+++ b/api/CourseRegistration.Tests/Services/MathServiceTests.cs
@@ -0,0 +1,75 @@
+using Xunit;
+using CourseRegistration.Application.Services;
+
+namespace CourseRegistration.Tests.Services;
+
+///
+/// Unit tests for factorial calculation.
+///
+public class MathServiceTests
+{
+ private readonly MathService _mathService = new();
+
+ // ── Base cases ─────────────────────────────────────────────────────────────
+
+ [Fact]
+ public void CalculateFactorial_Zero_ReturnsOne()
+ {
+ // Arrange / Act
+ var result = _mathService.CalculateFactorial(0);
+
+ // Assert
+ Assert.Equal(1L, result);
+ }
+
+ [Fact]
+ public void CalculateFactorial_One_ReturnsOne()
+ {
+ // Arrange / Act
+ var result = _mathService.CalculateFactorial(1);
+
+ // Assert
+ Assert.Equal(1L, result);
+ }
+
+ // ── Typical positive values ────────────────────────────────────────────────
+
+ [Theory]
+ [InlineData(2, 2L)]
+ [InlineData(3, 6L)]
+ [InlineData(4, 24L)]
+ [InlineData(5, 120L)]
+ [InlineData(10, 3628800L)]
+ [InlineData(15, 1307674368000L)]
+ [InlineData(20, 2432902008176640000L)]
+ public void CalculateFactorial_PositiveInput_ReturnsCorrectResult(int n, long expected)
+ {
+ // Arrange / Act
+ var result = _mathService.CalculateFactorial(n);
+
+ // Assert
+ Assert.Equal(expected, result);
+ }
+
+ // ── Error paths ────────────────────────────────────────────────────────────
+
+ [Theory]
+ [InlineData(-1)]
+ [InlineData(-100)]
+ [InlineData(int.MinValue)]
+ public void CalculateFactorial_NegativeInputs_ThrowsArgumentOutOfRangeException(int n)
+ {
+ // Arrange / Act / Assert
+ Assert.Throws(() => _mathService.CalculateFactorial(n));
+ }
+
+ [Theory]
+ [InlineData(21)]
+ [InlineData(100)]
+ [InlineData(int.MaxValue)]
+ public void CalculateFactorial_LargeInputs_ThrowsOverflowException(int n)
+ {
+ // Arrange / Act / Assert
+ Assert.Throws(() => _mathService.CalculateFactorial(n));
+ }
+}