content: {-# LANGUAGE ConstraintKinds #-}
  {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE GADTs #-}
  {-# LANGUAGE TypeApplications #-}
  {-# LANGUAGE TypeOperators #-}
  
  module Test.Sandwich.Contexts.Kubernetes.KindCluster.ServiceForwardPortForward where
  
  import Control.Monad.IO.Unlift
  import Control.Monad.Logger
  import qualified Data.List as L
  import Data.String.Interpolate
  import qualified Data.Text as T
  import Network.URI
  import Relude hiding (withFile)
  import Safe
  import Test.Sandwich
  import Test.Sandwich.Contexts.Kubernetes.KubectlPortForward
  import Test.Sandwich.Contexts.Kubernetes.Types
  import UnliftIO.Environment
  import UnliftIO.Process
  
  
  withForwardKubernetesService' :: (
    MonadUnliftIO m, MonadLoggerIO m
    , HasBaseContextMonad context m
    ) => KubernetesClusterContext -> FilePath -> Text -> Text -> (URI -> m a) -> m a
  withForwardKubernetesService' (KubernetesClusterContext {kubernetesClusterType=(KubernetesClusterKind {..}), ..}) kubectlBinary namespace service action = do
    baseEnv <- maybe getEnvironment return kubernetesClusterTypeKindClusterEnvironment
    let env = L.nubBy (\x y -> fst x == fst y) (("KUBECONFIG", kubernetesClusterKubeConfigPath) : baseEnv)
  
    portRaw <- (toString . T.strip . toText) <$> readCreateProcessWithLogging (
      (proc kubectlBinary [
        "get"
        , "service", toString service
        , "--namespace", toString namespace
        , [i|-o=jsonpath={.spec.ports[0].port}|]
        ]) { env = Just env }) ""
  
    port <- case readMay portRaw of
      Just p -> pure p
      Nothing -> expectationFailure [i|Failed to parse service port: #{portRaw}|]
  
    withKubectlPortForward' kubectlBinary kubernetesClusterKubeConfigPath namespace (const True) Nothing ("svc/" <> service) port $ \(KubectlPortForwardContext {..}) -> do
      action $ nullURI {
        uriScheme = "http:"
        , uriAuthority = Just (nullURIAuth {
                                  uriRegName = "localhost"
                                  , uriPort = ":" <> show kubectlPortForwardPort
                                  })
        }
  
  withForwardKubernetesService' _ _ _ _ _ = error "withForwardKubernetesService' must be called with a kind KubernetesClusterContext"
  