{-|
Module      : Core.Utils
Description :
Copyright   : (c) CNRS, 2017-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX

-}

module Test.Core.Utils where

import Data.Time (toGregorian, utctDay, utctDayTime)
import Data.Time.LocalTime (TimeOfDay(..), timeOfDayToTime)
import Gargantext.Core.Utils
import Gargantext.Core.Utils.DateUtils (dateParts, parseFlexibleTime, toUTCTime, toUTCTimeR)
import Gargantext.Prelude
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.Instances ()


-- | Core.Utils tests
test :: Spec
test = do
  describe "array utils work" $ do
    describe "check if groupWithCounts works" $ do
      it "simple integer array" $ do
        let testArray :: [Int]
            testArray = [1, 2, 3, 1, 2, 3]
            groupedArray :: [(Int, Int)]
            groupedArray = [(1, 2), (2, 2), (3, 2)]
        groupWithCounts testArray  `shouldBe` groupedArray
      it "string"               $ do
        let testString :: [Char]
            testString = "abccba"
            groupedString :: [(Char, Int)]
            groupedString = [('a', 2), ('b', 2), ('c', 2)]
        groupWithCounts testString `shouldBe` groupedString
    describe "check nonemptyIntercalate" $ do
      it "empty list" $ nonemptyIntercalate "," [] `shouldBe` ""
      it "simple list" $ nonemptyIntercalate "," ["x"] `shouldBe` "x"
      it "two-element list" $ nonemptyIntercalate "," ["x", "y"] `shouldBe` "x,y"
      it "with empty strings" $ nonemptyIntercalate "," ["a", "", "b", "", "c", ""] `shouldBe` "a,b,c"
      
  describe "DateUtils" $ do
    describe "UTCTimeR works" $ do
      prop "can convert to/from" $
        \utcTimeR -> toUTCTimeR (toUTCTime utcTimeR) == utcTimeR
    describe "parseFlexibleTime works" $ do
      it "ISO8601 format works 1" $ do
        let parsed = parseFlexibleTime "2025-05-04T12:05:01.000Z"
        (toGregorian . utctDay) <$> parsed `shouldBe` (Just (2025, 5, 4))
        utctDayTime <$> parsed `shouldBe` (Just $ timeOfDayToTime $ TimeOfDay 12 5 1)
      it "ISO8601 format works 2" $ do
        let parsed = parseFlexibleTime "2025-05-04T12:05:01Z"
        (toGregorian . utctDay) <$> parsed `shouldBe` (Just (2025, 5, 4))
        utctDayTime <$> parsed `shouldBe` (Just $ timeOfDayToTime $ TimeOfDay 12 5 1)
      it "'2025-07-20T01:00:13' format works" $ do
        let parsed = parseFlexibleTime "2025-07-20T01:00:13"
        (toGregorian . utctDay) <$> parsed `shouldBe` (Just (2025, 7, 20))
        utctDayTime <$> parsed `shouldBe` (Just $ timeOfDayToTime $ TimeOfDay 1 0 13)
      it "'2025-07-20 01:00:13' format works" $ do
        let parsed = parseFlexibleTime "2025-07-20 01:00:13"
        (toGregorian . utctDay) <$> parsed `shouldBe` (Just (2025, 7, 20))
        utctDayTime <$> parsed `shouldBe` (Just $ timeOfDayToTime $ TimeOfDay 1 0 13)
      it "'2025-07-20 01:00:13 UTC' format works" $ do
        let parsed = parseFlexibleTime "2025-07-20 01:00:13 UTC"
        (toGregorian . utctDay) <$> parsed `shouldBe` (Just (2025, 7, 20))
        utctDayTime <$> parsed `shouldBe` (Just $ timeOfDayToTime $ TimeOfDay 1 0 13)
    describe "dateParts works" $ do
      it "ISO8601 format works 1" $
        dateParts "2025-05-04T12:05:01.000Z" `shouldBe` ["2025", "05", "04"]
      it "ISO8601 format works 2" $
        dateParts "2025-05-04T12:05:01Z" `shouldBe` ["2025", "05", "04"]
      it "'2025-07-20 01:00:13 UTC' format works" $
        dateParts "2025-07-20 01:00:13 UTC" `shouldBe` ["2025", "07", "20"]
