-- SPDX-License-Identifier: Apache-2.0
-- Copyright 2025 ThreeSum Test Suite
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.

{-|
Module      : TestThreeSum
Description : Test suite for the 3Sum solution
Copyright   : (c) 2025
License     : Apache-2.0

Comprehensive test suite to verify the correctness of the 3Sum implementation.
-}

import ThreeSum
import Data.List (sort)

-- | Test if all triplets in the result sum to zero
testSumToZero :: [Triplet] -> Bool
testSumToZero = all (\(a, b, c) -> a + b + c == 0)

-- | Test if there are no duplicate triplets
testNoDuplicates :: [Triplet] -> Bool
testNoDuplicates triplets = length triplets == length (removeDups triplets)
  where
    removeDups = map head . group . sort
    group [] = []
    group (x:xs) = (x : takeWhile (== x) xs) : group (dropWhile (== x) xs)

-- | Run all test cases
runTests :: IO ()
runTests = do
  putStrLn "Running 3Sum Test Suite"
  putStrLn "======================="
  
  -- Test Case 1: Standard LeetCode example
  let test1 = [-1, 0, 1, 2, -1, -4]
  let result1 = threeSum test1
  putStrLn $ "Test 1 - Input: " ++ show test1
  putStrLn $ "Result: " ++ show result1
  putStrLn $ "All sum to zero: " ++ show (testSumToZero result1)
  putStrLn $ "No duplicates: " ++ show (testNoDuplicates result1)
  putStrLn ""
  
  -- Test Case 2: No valid triplets
  let test2 = [0, 1, 1]
  let result2 = threeSum test2
  putStrLn $ "Test 2 - Input: " ++ show test2
  putStrLn $ "Result: " ++ show result2
  putStrLn $ "Should be empty: " ++ show (null result2)
  putStrLn ""
  
  -- Test Case 3: All zeros
  let test3 = [0, 0, 0]
  let result3 = threeSum test3
  putStrLn $ "Test 3 - Input: " ++ show test3
  putStrLn $ "Result: " ++ show result3
  putStrLn $ "All sum to zero: " ++ show (testSumToZero result3)
  putStrLn ""
  
  -- Test Case 4: Multiple valid triplets
  let test4 = [-2, 0, 1, 1, 2]
  let result4 = threeSum test4
  putStrLn $ "Test 4 - Input: " ++ show test4
  putStrLn $ "Result: " ++ show result4
  putStrLn $ "All sum to zero: " ++ show (testSumToZero result4)
  putStrLn $ "No duplicates: " ++ show (testNoDuplicates result4)
  putStrLn ""
  
  -- Test Case 5: Edge case - less than 3 elements
  let test5 = [1, 2]
  let result5 = threeSum test5
  putStrLn $ "Test 5 - Input: " ++ show test5
  putStrLn $ "Result: " ++ show result5
  putStrLn $ "Should be empty: " ++ show (null result5)

main :: IO ()
main = runTests