content: module IHP.IDE.CodeGen.JobGenerator (buildPlan, buildPlan', JobConfig (..)) where
  
  import IHP.Prelude
  import qualified Data.Text as Text
  import IHP.IDE.CodeGen.Types
  import qualified System.Directory as Directory
  
  data JobConfig = JobConfig
      { applicationName :: Text
      , tableName :: Text -- E.g. create_container_jobs
      , modelName :: Text -- E.g. CreateContainerJob
      , isFirstJobInApplication :: Bool -- If true, creates Worker.hs in application directory
      } deriving (Eq, Show)
  
  buildPlan :: Text -> Text -> IO (Either Text [GeneratorAction])
  buildPlan jobName applicationName = do
      isFirstJobInApplication <- not <$> Directory.doesFileExist (cs $ applicationName <> "/Worker.hs")
      if null jobName
          then pure $ Left "Job name cannot be empty"
          else do
              let jobConfig = JobConfig
                      { applicationName
                      , tableName = jobName
                      , modelName = tableNameToModelName jobName
                      , isFirstJobInApplication
                      }
              pure $ Right $ buildPlan' jobConfig
  
  -- E.g. qualifiedMailModuleName config "Confirmation" == "Web.Mail.Users.Confirmation"
  qualifiedJobModuleName :: JobConfig -> Text
  qualifiedJobModuleName config =
      config.applicationName <> ".Job." <> unqualifiedJobModuleName config
  
  unqualifiedJobModuleName :: JobConfig -> Text
  unqualifiedJobModuleName config = Text.replace "Job" "" (config.modelName)
  
  buildPlan' :: JobConfig -> [GeneratorAction]
  buildPlan' config =
          let
              name = config.modelName
              tableName = modelNameToTableName nameWithSuffix
              nameWithSuffix = if "Job" `isSuffixOf` name
                  then name
                  else name <> "Job" --e.g. "Test" -> "TestJob"
              nameWithoutSuffix = if "Job" `isSuffixOf` name
                  then Text.replace "Job" "" name
                  else name --e.g. "TestJob" -> "Test""
  
              job =
                  ""
                  <> "module " <> qualifiedJobModuleName config <> " where\n"
                  <> "import " <> config.applicationName <> ".Controller.Prelude\n"
                  <> "\n"
                  <> "instance Job " <> nameWithSuffix <> " where\n"
                  <> "    perform " <> nameWithSuffix <> " { .. } = do\n"
                  <> "        putStrLn \"Hello World!\"\n"
  
              schemaSql =
                  ""
                  <> "CREATE TABLE " <> tableName <> " (\n"
                  <> "    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,\n"
                  <> "    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n"
                  <> "    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n"
                  <> "    status JOB_STATUS DEFAULT 'job_status_not_started' NOT NULL,\n"
                  <> "    last_error TEXT DEFAULT NULL,\n"
                  <> "    attempts_count INT DEFAULT 0 NOT NULL,\n"
                  <> "    locked_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,\n"
                  <> "    locked_by UUID DEFAULT NULL,\n"
                  <> "    run_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL\n"
                  <> ");\n"
  
  
              emptyWorkerHs :: Text
              emptyWorkerHs =
                          let
                              applicationName = config.applicationName
                          in cs [plain|module #{applicationName}.Worker where
  
  import IHP.Prelude
  import #{applicationName}.Types
  import Generated.Types
  import IHP.Job.Runner
  import IHP.Job.Types
  
  import #{qualifiedJobModuleName config}
  
  instance Worker #{applicationName}Application where
      workers _ =
          [ worker @#{nameWithSuffix}
          -- Generator Marker
          ]
  |]
          in
              [ EnsureDirectory { directory = config.applicationName <> "/Job" }
              , AppendToFile { filePath = "Application/Schema.sql", fileContent = schemaSql }
              , CreateFile { filePath = config.applicationName <> "/Job/" <> nameWithoutSuffix <> ".hs", fileContent = job }
              ]
              <> if config.isFirstJobInApplication
                      then [ CreateFile { filePath = config.applicationName <> "/Worker.hs", fileContent = emptyWorkerHs } ]
                      else
                          [ AddImport { filePath = config.applicationName <> "/Worker.hs", fileContent = "import " <> qualifiedJobModuleName config }
                          , AppendToMarker { marker = "-- Generator Marker", filePath = config.applicationName <> "/Worker.hs", fileContent = "        , worker @" <> nameWithSuffix }
                          ]
  