content: -- Licensed to the Apache Software Foundation (ASF) under one
  -- or more contributor license agreements.  See the NOTICE file
  -- distributed with this work for additional information
  -- regarding copyright ownership.  The ASF licenses this file
  -- to you 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 PerformanceTest (performanceTests) where
  
  import Control.Monad.IO.Class (MonadIO, liftIO)
  import qualified Data.ByteString.Char8 as BS8
  import Data.Time
  import OpenDAL
  import Test.Tasty
  import Test.Tasty.HUnit
  
  performanceTests :: TestTree
  performanceTests =
    testGroup
      "Performance Tests"
      [ testCase "testBulkOperations" testBulkOperations,
        testCase "testWriterVsDirectWrite" testWriterVsDirectWrite,
        testCase "testLargeFileOperations" testLargeFileOperations,
        testCase "testConcurrentOperations" testConcurrentOperations
      ]
  
  testBulkOperations :: Assertion
  testBulkOperations = do
    Right op <- newOperator "memory"
    
    -- Test bulk write operations
    start <- getCurrentTime
    mapM_ (\i -> writeOpRaw op ("bulk-file-" ++ show i) (BS8.pack ("content-" ++ show i)) ?= Right ()) [1..100 :: Int]
    writeEnd <- getCurrentTime
    
    -- Test bulk read operations  
    mapM_ (\i -> readOpRaw op ("bulk-file-" ++ show i) ?= Right (BS8.pack ("content-" ++ show i))) [1..100 :: Int]
    readEnd <- getCurrentTime
    
    let writeTime = diffUTCTime writeEnd start
        readTime = diffUTCTime readEnd writeEnd
    
    -- Just verify operations completed (performance checks are informational)
    putStrLn $ "Bulk write time: " ++ show writeTime
    putStrLn $ "Bulk read time: " ++ show readTime
    
    -- Verify correctness
    readOpRaw op "bulk-file-50" ?= Right (BS8.pack "content-50")
  
  testWriterVsDirectWrite :: Assertion
  testWriterVsDirectWrite = do
    Right op <- newOperator "memory"
    
  
    
    -- Test writer approach
    start1 <- getCurrentTime
    Right writer <- writerOpRaw op "writer-test" defaultWriterOption
    mapM_ (\_ -> writerWrite writer "chunk" ?= Right ()) [1..100 :: Int]
    Right _ <- writerClose writer
    end1 <- getCurrentTime
    
    -- Test direct write approach  
    start2 <- getCurrentTime
    let combinedData = BS8.concat $ Prelude.replicate 100 (BS8.pack "chunk")
    writeOpRaw op "direct-test" combinedData ?= Right ()
    end2 <- getCurrentTime
    
    let writerTime = diffUTCTime end1 start1
        directTime = diffUTCTime end2 start2
    
    putStrLn $ "Writer approach time: " ++ show writerTime
    putStrLn $ "Direct write time: " ++ show directTime
    
    -- Verify both approaches produce same result
    Right writerContent <- readOpRaw op "writer-test"
    Right directContent <- readOpRaw op "direct-test"
    writerContent @?= directContent
  
  testLargeFileOperations :: Assertion
  testLargeFileOperations = do
    Right op <- newOperator "memory"
    
    -- Create a 1MB file using writer
    let chunkSize = 1024 -- 1KB chunks
        numChunks = 1024 -- 1024 chunks = 1MB
        chunk = BS8.replicate chunkSize 'X'
    
    start <- getCurrentTime
    Right writer <- writerOpRaw op "large-file" defaultWriterOption
    mapM_ (\_ -> writerWrite writer chunk ?= Right ()) [1..numChunks]
    Right meta <- writerClose writer
    end <- getCurrentTime
    
    let writeTime = diffUTCTime end start
    putStrLn $ "Large file (1MB) write time: " ++ show writeTime
    
    -- Verify file size
    mContentLength meta @?= fromIntegral (chunkSize * numChunks)
    
    -- Test reading the large file
    start2 <- getCurrentTime
    Right content <- readOpRaw op "large-file"
    end2 <- getCurrentTime
    
    let readTime = diffUTCTime end2 start2
    putStrLn $ "Large file (1MB) read time: " ++ show readTime
    
    -- Verify content correctness (just check size and first/last bytes)
    BS8.length content @?= chunkSize * numChunks
    BS8.head content @?= 'X'
    BS8.last content @?= 'X'
  
  testConcurrentOperations :: Assertion
  testConcurrentOperations = do
    Right op <- newOperator "memory"
    
    -- Simulate concurrent operations by interleaving writes and reads
    start <- getCurrentTime
    
    -- Write some files
    mapM_ (\i -> writeOpRaw op ("concurrent-" ++ show i) (BS8.pack ("data-" ++ show i)) ?= Right ()) [1..50 :: Int]
    
    -- Read while writing more
    mapM_ (\i -> do
      writeOpRaw op ("concurrent-extra-" ++ show i) (BS8.pack ("extra-" ++ show i)) ?= Right ()
      readOpRaw op ("concurrent-" ++ show i) ?= Right (BS8.pack ("data-" ++ show i))
      ) [1..25 :: Int]
    
    end <- getCurrentTime
    let totalTime = diffUTCTime end start
    putStrLn $ "Concurrent operations time: " ++ show totalTime
    
    -- Verify some operations completed correctly
    readOpRaw op "concurrent-10" ?= Right (BS8.pack "data-10")
    readOpRaw op "concurrent-extra-10" ?= Right (BS8.pack "extra-10")
  
  -- helper function
  
  (?=) :: (MonadIO m, Eq a, Show a) => m a -> a -> m ()
  result ?= except = result >>= liftIO . (@?= except) 