-- SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

{-# LANGUAGE TypeApplications #-}

module Handler.SAP
  ( getQualificationSAPDirectR
  )
  where

import Import

import Handler.Utils
import Handler.Utils.Csv
import Handler.Utils.Profile

-- import qualified Data.CaseInsensitive as CI
import qualified Data.Csv as Csv
import           Database.Esqueleto.Experimental ((:&)(..))
import qualified Database.Esqueleto.Experimental as Ex -- needs TypeApplications Lang-Pragma
-- import qualified Database.Esqueleto.Legacy as E
import qualified Database.Esqueleto.Utils as E


data SapUserTableCsv = SapUserTableCsv -- for csv export only
  { csvSUTpersonalNummer :: Text 
  , csvSUTqualifikation  :: Text
  , csvSUTgültigVon      :: Day
  , csvSUTgültigBis      :: Day  
  -- , csvSUTsupendiertBis  :: Maybe Day
  , csvSUTausprägung     :: Text
  }
  deriving (Show, Generic)
makeLenses_ ''SapUserTableCsv

sapUserTableCsvHeader :: Csv.Header
sapUserTableCsvHeader = Csv.header 
    [ "PersonalNummer"
    , "Qualifikation"
    , "GültigVon"
    , "GültigBis"
    -- , "SupendiertBis"
    , "Ausprägung"
    ]

instance ToNamedRecord SapUserTableCsv where
  toNamedRecord SapUserTableCsv{..} = Csv.namedRecord
    [ "PersonalNummer"  Csv..= csvSUTpersonalNummer
    , "Qualifikation"   Csv..= csvSUTqualifikation
    , "GültigVon"       Csv..= csvSUTgültigVon   
    , "GültigBis"       Csv..= csvSUTgültigBis     
    -- , "SupendiertBis"   Csv..= csvSUTsupendiertBis
    , "Ausprägung"      Csv..= csvSUTausprägung   
    ]

-- | Removes all personalNummer which are not numbers between 10000 and 99999 (also excludes E-Accounts), which should not be returned by the query anyway (only qualfications with sap id and users with internal personnel number must be transmitted)
--   TODO: once temporary suspensions are implemented, a user must be transmitted to SAP in two rows: firstheld->suspensionFrom & suspensionTo->validTo
sapRes2csv :: [(Ex.Value (Maybe Text), Ex.Value Day, Ex.Value Day, Ex.Value (Maybe Text))] -> [SapUserTableCsv]
sapRes2csv l = [ res | (Ex.Value pn@(Just persNo), Ex.Value firstHeld, Ex.Value validUntil, Ex.Value (Just sapId)) <- l 
                --  , let persNoAsInt = readMay =<< persNo -- also see Handler.Utils.Profile.validFraportPersonalNumber
                --  , persNoAsInt >= Just (10000::Int)       -- filter E-accounts for SAP export
                --  , persNoAsInt <= Just (99999::Int)       -- filter E-accounts for SAP export                                                     
                , let res = SapUserTableCsv
                            { csvSUTpersonalNummer = persNo
                            , csvSUTqualifikation  = sapId
                            , csvSUTgültigVon      = firstHeld
                            , csvSUTgültigBis      = validUntil
                            -- , csvSUTsupendiertBis  = blocked
                            , csvSUTausprägung     = "J"
                            }
                , validFraportPersonalNumber pn
               ]

-- | Deliver all employess with a successful LDAP synch within the last 3 months
getQualificationSAPDirectR :: Handler TypedContent
getQualificationSAPDirectR = do
  now   <- liftIO getCurrentTime  
  fdate <- formatTime' "%Y%m%d_%H-%M" now 
  let ldap_cutoff = addDiffDaysRollOver (fromMonths $ -3) now
  qualUsers <- runDB $ Ex.select $ do
    (qual :& qualUser :& user) <- 
      Ex.from $ Ex.table @Qualification 
      `Ex.innerJoin` Ex.table @QualificationUser
      `Ex.on` (\(qual :& qualUser) -> qual Ex.^. QualificationId Ex.==. qualUser Ex.^. QualificationUserQualification)
      `Ex.innerJoin` Ex.table @User
      `Ex.on` (\(_ :& qualUser :& user) -> qualUser Ex.^. QualificationUserUser Ex.==. user Ex.^. UserId)
    Ex.where_ $ E.isJust (qual Ex.^. QualificationSapId)
        Ex.&&.  E.isJust (user Ex.^. UserCompanyPersonalNumber)
        Ex.&&.  E.isJust (user Ex.^. UserLastLdapSynchronisation)
        Ex.&&.  (E.justVal ldap_cutoff Ex.<=. user Ex.^. UserLastLdapSynchronisation)
    return 
      ( user      Ex.^. UserCompanyPersonalNumber
      , qualUser  Ex.^. QualificationUserFirstHeld
      , qualUser  Ex.^. QualificationUserValidUntil
      -- , qualUser  Ex.^. QualificationUserBlockedDue
      , qual      Ex.^. QualificationSapId
      )    
  let csvRendered = toCsvRendered sapUserTableCsvHeader $ sapRes2csv qualUsers
      fmtOpts = (review csvPreset CsvPresetRFC)
                    { csvIncludeHeader  = True
                    , csvDelimiter      = ','
                    , csvUseCrLf        = True
                    }
      csvOpts = def { csvFormat = fmtOpts }
      csvSheetName = "fradrive_sap_" <> fdate <> ".csv"
      nr  = length qualUsers
      msg = "Qualification download file " <> csvSheetName <> " containing " <> tshow nr <> " rows"  
  $logInfoS "SAP" msg
  addHeader "Content-Disposition" $ "attachment; filename=\"" <> csvSheetName <> "\""
  csvRenderedToTypedContentWith csvOpts csvSheetName csvRendered  

-- direct Download see:
-- https://ersocon.net/blog/2017/2/22/creating-csv-files-in-yesod
