module Python.PipenvSpec (
  spec,
) where

import Data.Aeson (eitherDecodeStrict)
import Data.ByteString qualified as BS
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import DepTypes
import GraphUtil
import Strategy.Python.Pipenv
import Test.Hspec hiding (xit)

pipfileLock :: PipfileLock
pipfileLock =
  PipfileLock
    { fileMeta =
        PipfileMeta
          [ PipfileSource
              { sourceName = "package-index"
              , sourceUrl = "-package-index/"
              }
          ]
    , fileDefault =
        Map.fromList
          [
            ( "pkgTwo"
            , PipfileDep
                { fileDepVersion = Just "==2.0.0"
                , fileDepIndex = Just "package-index"
                }
            )
          ,
            ( "pkgThree"
            , PipfileDep
                { fileDepVersion = Just "==3.0.0"
                , fileDepIndex = Nothing
                }
            )
          ,
            ( "pkgFour"
            , PipfileDep
                { fileDepVersion = Nothing
                , fileDepIndex = Nothing
                }
            )
          ]
    , fileDevelop =
        Map.fromList
          [
            ( "pkgOne"
            , PipfileDep
                { fileDepVersion = Just "==1.0.0"
                , fileDepIndex = Nothing
                }
            )
          ]
    }

pipenvOutput :: [PipenvGraphDep]
pipenvOutput =
  [ PipenvGraphDep
      { depName = "pkgOne"
      , depInstalled = "1.0.0"
      , depRequired = "==1.0.0"
      , depDependencies = []
      }
  , PipenvGraphDep
      { depName = "pkgTwo"
      , depInstalled = "2.0.0"
      , depRequired = "==2.0.0"
      , depDependencies =
          [ PipenvGraphDep
              { depName = "pkgThree"
              , depInstalled = "3.0.0"
              , depRequired = "==3.0.0"
              , depDependencies = []
              }
          ]
      }
  ]

depOne :: Dependency
depOne =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgOne"
    , dependencyVersion = Just (CEq "1.0.0")
    , dependencyLocations = []
    , dependencyEnvironments = Set.singleton EnvDevelopment
    , dependencyTags = Map.empty
    }

depTwo :: Dependency
depTwo =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgTwo"
    , dependencyVersion = Just (CEq "2.0.0")
    , dependencyLocations = ["-package-index/"]
    , dependencyEnvironments = Set.singleton EnvProduction
    , dependencyTags = Map.empty
    }

depThree :: Dependency
depThree =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgThree"
    , dependencyVersion = Just (CEq "3.0.0")
    , dependencyLocations = []
    , dependencyEnvironments = Set.singleton EnvProduction
    , dependencyTags = Map.empty
    }

depFour :: Dependency
depFour =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgFour"
    , dependencyVersion = Nothing
    , dependencyLocations = []
    , dependencyEnvironments = Set.singleton EnvProduction
    , dependencyTags = Map.empty
    }

xit :: String -> Expectation -> SpecWith (Arg Expectation)
xit _ _ = it "is an ignored test" $ () `shouldBe` ()

spec :: Spec
spec = do
  pipLockFile <- runIO (BS.readFile "test/Python/testdata/Pipfile.lock")

  describe "analyzeWithCmd" $
    -- FIXME: graphing needs to be refactored to include "reachable" alongside "direct"
    xit "should use pipenv output for edges and tags" $ do
      let result = buildGraph pipfileLock (Just pipenvOutput)

      expectDeps [depOne, depTwo, depThree] result
      expectDirect [depOne, depTwo] result
      expectEdges [(depTwo, depThree)] result

  describe "analyzeNoCmd" $
    it "should set all dependencies as direct" $ do
      let result = buildGraph pipfileLock Nothing

      expectDeps [depOne, depTwo, depThree, depFour] result
      expectDirect [depOne, depTwo, depThree, depFour] result
      expectEdges [] result

  describe "analyzeNoCmdFromFile" $
    it "should set all dependencies as direct" $ do
      case eitherDecodeStrict pipLockFile of
        Right res -> do
          let result = buildGraph res Nothing
          expectDeps [depOne, depTwo, depThree, depFour] result
          expectDirect [depOne, depTwo, depThree, depFour] result
          expectEdges [] result
        Left _ -> expectationFailure "failed to parse"

 FIXME: graphing needs to be refactored to include "reachable" alongside "direct"
module Python.PipenvSpec (
  spec,
) where

import Data.Aeson (eitherDecodeStrict)
import Data.ByteString qualified as BS
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import DepTypes
import GraphUtil
import Strategy.Python.Pipenv
import Test.Hspec hiding (xit)

pipfileLock :: PipfileLock
pipfileLock =
  PipfileLock
    { fileMeta =
        PipfileMeta
          [ PipfileSource
              { sourceName = "package-index"
              , sourceUrl = "-package-index/"
              }
          ]
    , fileDefault =
        Map.fromList
          [
            ( "pkgTwo"
            , PipfileDep
                { fileDepVersion = Just "==2.0.0"
                , fileDepIndex = Just "package-index"
                }
            )
          ,
            ( "pkgThree"
            , PipfileDep
                { fileDepVersion = Just "==3.0.0"
                , fileDepIndex = Nothing
                }
            )
          ,
            ( "pkgFour"
            , PipfileDep
                { fileDepVersion = Nothing
                , fileDepIndex = Nothing
                }
            )
          ]
    , fileDevelop =
        Map.fromList
          [
            ( "pkgOne"
            , PipfileDep
                { fileDepVersion = Just "==1.0.0"
                , fileDepIndex = Nothing
                }
            )
          ]
    }

pipenvOutput :: [PipenvGraphDep]
pipenvOutput =
  [ PipenvGraphDep
      { depName = "pkgOne"
      , depInstalled = "1.0.0"
      , depRequired = "==1.0.0"
      , depDependencies = []
      }
  , PipenvGraphDep
      { depName = "pkgTwo"
      , depInstalled = "2.0.0"
      , depRequired = "==2.0.0"
      , depDependencies =
          [ PipenvGraphDep
              { depName = "pkgThree"
              , depInstalled = "3.0.0"
              , depRequired = "==3.0.0"
              , depDependencies = []
              }
          ]
      }
  ]

depOne :: Dependency
depOne =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgOne"
    , dependencyVersion = Just (CEq "1.0.0")
    , dependencyLocations = []
    , dependencyEnvironments = Set.singleton EnvDevelopment
    , dependencyTags = Map.empty
    }

depTwo :: Dependency
depTwo =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgTwo"
    , dependencyVersion = Just (CEq "2.0.0")
    , dependencyLocations = ["-package-index/"]
    , dependencyEnvironments = Set.singleton EnvProduction
    , dependencyTags = Map.empty
    }

depThree :: Dependency
depThree =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgThree"
    , dependencyVersion = Just (CEq "3.0.0")
    , dependencyLocations = []
    , dependencyEnvironments = Set.singleton EnvProduction
    , dependencyTags = Map.empty
    }

depFour :: Dependency
depFour =
  Dependency
    { dependencyType = PipType
    , dependencyName = "pkgFour"
    , dependencyVersion = Nothing
    , dependencyLocations = []
    , dependencyEnvironments = Set.singleton EnvProduction
    , dependencyTags = Map.empty
    }

xit :: String -> Expectation -> SpecWith (Arg Expectation)
xit _ _ = it "is an ignored test" $ () `shouldBe` ()

spec :: Spec
spec = do
  pipLockFile <- runIO (BS.readFile "test/Python/testdata/Pipfile.lock")

  describe "analyzeWithCmd" $
    xit "should use pipenv output for edges and tags" $ do
      let result = buildGraph pipfileLock (Just pipenvOutput)

      expectDeps [depOne, depTwo, depThree] result
      expectDirect [depOne, depTwo] result
      expectEdges [(depTwo, depThree)] result

  describe "analyzeNoCmd" $
    it "should set all dependencies as direct" $ do
      let result = buildGraph pipfileLock Nothing

      expectDeps [depOne, depTwo, depThree, depFour] result
      expectDirect [depOne, depTwo, depThree, depFour] result
      expectEdges [] result

  describe "analyzeNoCmdFromFile" $
    it "should set all dependencies as direct" $ do
      case eitherDecodeStrict pipLockFile of
        Right res -> do
          let result = buildGraph res Nothing
          expectDeps [depOne, depTwo, depThree, depFour] result
          expectDirect [depOne, depTwo, depThree, depFour] result
          expectEdges [] result
        Left _ -> expectationFailure "failed to parse"
